ฉันไม่เข้าใจรูปแบบการออกแบบ "สะพาน" เลย ฉันได้ผ่านเว็บไซต์ต่าง ๆ แต่พวกเขาไม่ได้ช่วย
ใครช่วยฉันในการทำความเข้าใจสิ่งนี้
ฉันไม่เข้าใจรูปแบบการออกแบบ "สะพาน" เลย ฉันได้ผ่านเว็บไซต์ต่าง ๆ แต่พวกเขาไม่ได้ช่วย
ใครช่วยฉันในการทำความเข้าใจสิ่งนี้
คำตอบ:
ใน OOP เราใช้ polymorphism เพื่อให้นามธรรมสามารถมีการใช้งานที่หลากหลาย ลองดูตัวอย่างต่อไปนี้:
//trains abstraction
public interface Train
{
move();
}
public class MonoRail:Train
{
public override move()
{
//use one track;
}
}
public class Rail:Train
{
public override move()
{
//use two tracks;
}
}
ข้อกำหนดใหม่ได้รับการแนะนำและต้องการนำมาใช้ในมุมมองการเร่งความเร็วของรถไฟดังนั้นให้เปลี่ยนรหัสด้านล่าง
public interface Train
{
void move();
}
public class MonoRail:Train
{
public override void move()
{
//use one track;
}
}
public class ElectricMonoRail:MonoRail
{
public override void move()
{
//use electric engine on one track.
}
}
public class DieselMonoRail: MonoRail
{
public override void move()
{
//use diesel engine on one track.
}
}
public class Rail:Train
{
public override void move()
{
//use two tracks;
}
}
public class ElectricRail:Rail
{
public override void move()
{
//use electric engine on two tracks.
}
}
public class DieselRail: Rail
{
public override void move()
{
//use diesel engine on two tracks.
}
}
รหัสข้างต้นไม่สามารถบำรุงรักษาได้และขาดการนำกลับมาใช้ใหม่ (สมมติว่าเราสามารถใช้กลไกการเร่งความเร็วสำหรับแพลตฟอร์มแทร็กเดียวกัน) รหัสต่อไปนี้ใช้รูปแบบสะพานและแยกทั้งสองแนวคิดที่แตกต่างกัน, การขนส่งทางรถไฟและการเร่งความเร็ว
public interface Train
{
void move(Accelerable engine);
}
public interface Accelerable
{
public void accelerate();
}
public class MonoRail:Train
{
public override void move(Accelerable engine)
{
//use one track;
engine.accelerate(); //engine is pluggable (runtime dynamic)
}
}
public class Rail:Train
{
public override void move(Accelerable engine)
{
//use two tracks;
engine.accelerate(); //engine is pluggable (runtime dynamic)
}
}
public class ElectricEngine:Accelerable{/*implementation code for accelerable*/}
public class DieselEngine:Accelerable{/*implementation code for accelerable*/}
Monorail
เพราะไม่ใช่สองคำจริงๆเป็นคำเดียว (คำประสม) MonoRail จะเป็น subclass บางส่วนของ Rail แทนที่จะเป็น Rail แบบอื่น (ซึ่งก็คือ) เช่นเดียวกับที่เราจะไม่ใช้SunShine
หรือCupCake
พวกเขาจะเป็นSunshine
และCupcake
ในขณะที่รูปแบบการออกแบบส่วนใหญ่มีชื่อที่มีประโยชน์ แต่ฉันพบว่าชื่อ "Bridge" นั้นไม่ง่ายต่อการใช้งาน
แนวคิดคุณส่งรายละเอียดการใช้งานที่ใช้โดยลำดับชั้นของคลาสไปยังวัตถุอื่นโดยทั่วไปจะมีลำดับชั้นของตัวเอง ด้วยการทำเช่นนี้คุณกำลังลบการพึ่งพารายละเอียดการใช้งานเหล่านั้นอย่างแน่นหนาและอนุญาตให้รายละเอียดของการปรับใช้นั้นเปลี่ยนแปลง
ในระดับน้อยฉันเปรียบสิ่งนี้กับการใช้รูปแบบกลยุทธ์ในวิธีที่คุณสามารถเสียบพฤติกรรมใหม่ แต่แทนที่จะห่อหุ้มอัลกอริทึมที่มักจะเห็นในกลยุทธ์วัตถุการใช้งานมักจะเต็มไปด้วยคุณสมบัติ และเมื่อคุณใช้แนวคิดกับลำดับชั้นของคลาสทั้งหมดรูปแบบที่ใหญ่กว่าจะกลายเป็นบริดจ์ (เกลียดชื่ออีกครั้ง)
ไม่ใช่รูปแบบที่คุณจะใช้ทุกวัน แต่ฉันพบว่ามีประโยชน์เมื่อจัดการการระเบิดของชั้นเรียนที่อาจเกิดขึ้นเมื่อคุณมีความต้องการ (ชัดเจน) สำหรับมรดกหลาย ๆ อย่าง
นี่คือตัวอย่างจริงของโลก:
ฉันมีเครื่องมือ RAD ที่ให้คุณดรอปและกำหนดค่าการควบคุมบนพื้นผิวการออกแบบดังนั้นฉันจึงมีโมเดลวัตถุเช่นนี้:
Widget // base class with design surface plumbing
+ Top
+ Left
+ Width
+ Height
+ Name
+ SendToBack
+ BringToFront
+ OnPropertyEdit
+ OnSelect
+ Validate
+ ShowEditor
+ Paint
+ Etc
TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor // override base to show a property editor form specific to a Textbox
+ Paint // override to render a textbox onto the surface
+ Etc
ListWidget : Widget // list specific
+ Items
+ SelectedItem
+ ShowEditor // override base to show a property editor form specific to a List
+ Paint // override to render a list onto the surface
+ Etc
และบางทีอาจมีการควบคุมเป็นโหล
แต่จะมีการเพิ่มข้อกำหนดใหม่เพื่อรองรับหลายธีม (look-n-feel) สมมติว่าเรามีรูปแบบต่อไปนี้: Win32
, WinCE
, WinPPC
, WinMo50
,WinMo65
, แต่ละธีมจะมีค่าหรือการใช้งานที่แตกต่างกันสำหรับการดำเนินการที่เกี่ยวข้องกับการเรนเดอร์เช่น DefaultFont, DefaultBackColor, BorderWidth, DrawFrame, DrawScrollThumb เป็นต้น
ฉันสามารถสร้างแบบจำลองวัตถุเช่นนี้:
Win32TextboxWidget : TextboxWidget
Win32ListWidget : ListWidget
ฯลฯ สำหรับหนึ่งประเภทการควบคุม
WinCETextboxWidget : TextboxWidget
WinCEListWidget : ListWidget
ฯลฯ สำหรับประเภทการควบคุมซึ่งกันและกัน (อีกครั้ง)
คุณได้รับแนวคิด - คุณได้รับการระเบิดในระดับ # จำนวนวิดเจ็ตคูณด้วย # ของธีม สิ่งนี้ทำให้ผู้ออกแบบ RAD ยุ่งยากขึ้นโดยทำให้ตระหนักถึงทุกธีม นอกจากนี้การเพิ่มธีมใหม่จะบังคับให้ RAD ดีไซเนอร์ต้องถูกแก้ไข นอกจากนี้ยังมีการใช้งานร่วมกันจำนวนมากภายในชุดรูปแบบที่จะเป็นการดีที่จะสืบทอด แต่ตัวควบคุมกำลังสืบทอดจากฐานร่วม ( Widget
)
ดังนั้นสิ่งที่ฉันทำคือสร้างลำดับชั้นของวัตถุแยกต่างหากที่ใช้ธีม แต่ละวิดเจ็ตจะมีการอ้างอิงไปยังวัตถุที่ใช้การดำเนินการการแสดงผล ในหลายตำราชั้นนี้จะต่อท้ายด้วยImpl
แต่ฉันเบี่ยงเบนไปจากแบบแผนการตั้งชื่อนั้น
ดังนั้นตอนนี้ฉันTextboxWidget
ดูเหมือนว่านี้:
TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor
+ Painter // reference to the implementation of the widget rendering operations
+ Etc
และฉันสามารถให้ช่างทาสีหลายคนสืบทอดฐานเฉพาะธีมของฉันซึ่งฉันไม่สามารถทำได้มาก่อน:
Win32WidgetPainter
+ DefaultFont
+ DefaultFontSize
+ DefaultColors
+ DrawFrame
+ Etc
Win32TextboxPainter : Win32WidgetPainter
Win32ListPainter : Win32WidgetPainter
หนึ่งในสิ่งที่ดีคือฉันสามารถโหลดแอพพลิเคชั่นในขณะใช้งานได้แบบไดนามิกทำให้ฉันสามารถเพิ่มธีมได้มากเท่าที่ฉันต้องการโดยไม่ต้องเปลี่ยนซอฟต์แวร์หลัก กล่าวอีกนัยหนึ่ง "การใช้งานของฉันอาจแตกต่างกันไปตามนามธรรม"
Win32TextboxPainter
และจากWin32ListPainter
Win32WidgetPainter
คุณสามารถมีต้นไม้มรดกในด้านการดำเนินการ แต่มันควรจะเป็นทั่วไปมากขึ้น (บางทีStaticStyleControlPainter
, EditStyleControlPainter
และButtonStyleControlPainter
) มีการดำเนินงานใด ๆ ที่จำเป็นดั้งเดิมแทนที่ตามความจำเป็น นี่ใกล้กับรหัสจริงที่ฉันยกมาเป็นตัวอย่าง
สะพานมีความตั้งใจที่จะแยกสิ่งที่เป็นนามธรรมออกจากการดำเนินการที่เป็นรูปธรรมเพื่อให้ทั้งสองสามารถเปลี่ยนแปลงได้อย่างอิสระ:
สะพานบรรลุเป้าหมายนี้โดยใช้การประพันธ์:
ข้อสังเกตเพิ่มเติมเกี่ยวกับความสับสนบ่อยครั้ง
รูปแบบนี้คล้ายกับรูปแบบของอะแดปเตอร์: สิ่งที่เป็นนามธรรมนำเสนออินเทอร์เฟซที่แตกต่างกันสำหรับการใช้งานและใช้การจัดองค์ประกอบเพื่อทำเช่นนั้น แต่:
ความแตกต่างที่สำคัญระหว่างรูปแบบเหล่านี้อยู่ในความตั้งใจของพวกเขา
- Gamma & al ใน" รูปแบบการออกแบบองค์ประกอบของซอฟต์แวร์ OO ที่ใช้ซ้ำได้ " , 1995
ในหนังสือน้ำเชื้อที่ยอดเยี่ยมนี้เกี่ยวกับรูปแบบการออกแบบผู้เขียนยังสังเกตเห็นว่า: