อ่าน 9 นาที
รูปแบบอะแดปเตอร์
ใน วิศวกรรมซอฟต์แวร์ รูป แบบอะแดปเตอร์ เป็น รูปแบบการออกแบบซอฟต์แวร์ (เรียกอีกอย่างว่า wrapper ซึ่งเป็นชื่อเรียกอีกชื่อหนึ่งที่ใช้ร่วมกับ รูปแบบเดโคเรเตอร์ ) ที่อนุญาตให้ใช้...
รูปแบบอะแดปเตอร์
ในวิศวกรรมซอฟต์แวร์รูปแบบอะแดปเตอร์เป็นรูปแบบการออกแบบซอฟต์แวร์ (เรียกอีกอย่างว่าwrapperซึ่งเป็นชื่อเรียกอีกชื่อหนึ่งที่ใช้ร่วมกับรูปแบบเดโคเรเตอร์ ) ที่อนุญาตให้ใช้อินเทอร์เฟซของคลาส ที่มีอยู่เป็นอินเทอร์เฟซอื่น [ 1 ] : 244 มักใช้เพื่อทำให้คลาสที่มีอยู่ทำงานร่วมกับคลาสอื่นได้โดยไม่ต้องแก้ไข ซอร์สโค้ด
ตัวอย่างหนึ่งคืออะแดปเตอร์ที่แปลงอินเทอร์เฟซของDocument Object Model (DMO)ของ เอกสาร XMLให้เป็นโครงสร้างแบบต้นไม้ที่สามารถแสดงผลได้
ภาพรวม
รูปแบบการออกแบบ อะแดปเตอร์[ 2 ]เป็นหนึ่งใน 23 รูปแบบการออกแบบ Gang of Four ที่รู้จักกันดี ซึ่งอธิบายวิธีการแก้ปัญหาการออกแบบที่เกิดขึ้นซ้ำๆ เพื่อออกแบบซอฟต์แวร์เชิงวัตถุที่มีความยืดหยุ่นและนำกลับมาใช้ใหม่ได้ กล่าวคือ วัตถุที่ง่ายต่อการใช้งาน เปลี่ยนแปลง ทดสอบ และนำกลับมาใช้ใหม่
รูปแบบการออกแบบอะแดปเตอร์ช่วยแก้ปัญหาต่างๆ เช่น: [ 3 ]
- จะนำคลาสที่ไม่มีอินเทอร์เฟซที่ไคลเอ็นต์ต้องการมาใช้ซ้ำได้อย่างไร?
- คลาสที่มีอินเทอร์เฟซไม่เข้ากันจะทำงานร่วมกันได้อย่างไร?
- จะสามารถจัดเตรียมอินเทอร์เฟซทางเลือกสำหรับคลาสได้อย่างไร?
บ่อยครั้งที่คลาส (ที่มีอยู่แล้ว) ไม่สามารถนำมาใช้ซ้ำได้เพียงเพราะอินเทอร์เฟซของคลาสนั้นไม่ตรงกับอินเทอร์เฟซที่ผู้ใช้งานต้องการ
รูปแบบการออกแบบอะแดปเตอร์อธิบายถึงวิธีการแก้ปัญหาดังกล่าว:
- กำหนด
adapterคลาสแยกต่างหากที่แปลงอินเทอร์เฟซ (ที่ไม่เข้ากัน) ของคลาส (adaptee) ให้เป็นอินเทอร์เฟซอื่น (target) ที่ไคลเอ็นต์ต้องการ - ดำเนินการตามขั้นตอน
adapterเพื่อใช้งาน (นำกลับมาใช้ใหม่) คลาสที่ไม่มีอินเทอร์เฟซที่จำเป็น
แนวคิดหลักในรูปแบบนี้คือการทำงานผ่านส่วนต่อประสานadapterที่ปรับเปลี่ยนส่วนต่อประสานของคลาส (ที่มีอยู่แล้ว) โดยไม่เปลี่ยนแปลงคลาสเดิม
ลูกค้าไม่ทราบว่าพวกเขากำลังทำงานกับtargetคลาสโดยตรงหรือผ่านadapterคลาสที่ไม่มีtargetอินเทอร์เฟซ
โปรดดูแผนภาพคลาส UML ด้านล่างด้วย
คำนิยาม
อะแดปเตอร์ช่วยให้สองอินเทอร์เฟซที่ไม่เข้ากันสามารถทำงานร่วมกันได้ นี่คือคำจำกัดความในโลกแห่งความเป็นจริงของอะแดปเตอร์ อินเทอร์เฟซอาจไม่เข้ากัน แต่ฟังก์ชันการทำงานภายในควรเหมาะสมกับความต้องการ รูปแบบการออกแบบอะแดปเตอร์ช่วยให้คลาสที่ไม่เข้ากันสามารถทำงานร่วมกันได้โดยการแปลงอินเทอร์เฟซของคลาสหนึ่งให้เป็นอินเทอร์เฟซที่ไคลเอ็นต์คาดหวัง
การใช้งาน
สามารถใช้อะแดปเตอร์ได้เมื่อตัวห่อต้องเคารพอินเทอร์เฟซเฉพาะและต้องรองรับพฤติกรรมแบบโพลีมอร์ฟิก ในทางกลับกัน รูปแบบตัวตกแต่งทำให้สามารถเพิ่มหรือเปลี่ยนแปลงพฤติกรรมของอินเทอร์เฟซในขณะรันไทม์ได้ และรูปแบบฟาซาดจะใช้เมื่อต้องการอินเทอร์เฟซที่ง่ายกว่าหรือเรียบง่ายกว่าสำหรับวัตถุพื้นฐาน[ 1 ] : 243, 252, 258, 260
| ลวดลาย | เจตนา |
|---|---|
| อะแดปเตอร์หรือตัวห่อหุ้ม | แปลงอินเทอร์เฟซหนึ่งไปเป็นอีกอินเทอร์เฟซหนึ่งเพื่อให้ตรงกับสิ่งที่ลูกค้าคาดหวัง |
| นักตกแต่ง | เพิ่มความรับผิดชอบให้กับอินเทอร์เฟซแบบไดนามิกโดยการห่อหุ้มโค้ดเดิม |
| คณะผู้แทน | สนับสนุน "การประกอบมากกว่าการสืบทอด" |
| ด้านหน้าอาคาร | มีอินเทอร์เฟซที่เรียบง่าย |
โครงสร้าง
แผนภาพคลาส UML

ในแผนภาพคลาสUML ด้านบน คลาสที่ต้องการอินเทอร์เฟซไม่สามารถนำคลาสนั้นมาใช้ซ้ำได้โดยตรง เนื่องจากอินเทอร์เฟซของคลาสนั้นไม่สอดคล้องกับอินเทอร์เฟซที่ต้องการ ดังนั้นจึงต้องใช้งานผ่านคลาสที่ใช้งานอินเทอร์เฟซนั้นแทน โดยมีลักษณะดังนี้: clienttargetadapteetargetclientadaptertargetadaptee
- วิธี การนี้
object adapterใช้อินtargetเทอร์เฟซโดยการมอบหมายให้กับadapteeอ็อบเจ็กต์ในขณะรันไทม์ (adaptee.specificOperation()) - วิธีการ นี้
class adapterใช้targetอินเทอร์เฟซโดยการสืบทอดจากadapteeคลาสในระหว่างการคอมไพล์ (specificOperation())
รูปแบบอะแดปเตอร์วัตถุ
ในรูปแบบ Adapter นี้ Adapter จะมีอินสแตนซ์ของคลาสที่มันห่อหุ้มอยู่ ในสถานการณ์นี้ Adapter จะเรียกใช้เมธอดไปยังอินสแตนซ์ของอ็อบเจ็กต์ ที่ถูกห่อ หุ้ม


รูปแบบอะแดปเตอร์คลาส
รูปแบบอะแดปเตอร์นี้ใช้อินเทอร์เฟซโพลีมอร์ฟิก หลายตัว ที่ใช้งานหรือสืบทอดทั้งอินเทอร์เฟซที่คาดหวังและอินเทอร์เฟซที่มีอยู่ก่อนแล้ว โดยทั่วไปอินเทอร์เฟซที่คาดหวังจะถูกสร้างขึ้นเป็นคลาสอินเทอร์เฟซ บริสุทธิ์ โดยเฉพาะใน ภาษาต่างๆเช่นJava (ก่อน JDK 1.8) ที่ไม่รองรับ การสืบทอด คลาสหลายชั้น[ 1 ] : 244


รูปแบบอะแดปเตอร์รันไทม์อีกรูปแบบหนึ่ง
แรงจูงใจจากโซลูชันในขั้นตอนการคอมไพล์
มีความต้องการที่classAจะป้อนclassBข้อมูลบางอย่าง สมมติว่าเป็นStringข้อมูลบางอย่าง วิธีแก้ปัญหาในขั้นตอนการคอมไพล์คือ:
คลาสบีsetStringData ( classA . getStringData ());อย่างไรก็ตาม สมมติว่ารูปแบบของข้อมูลสตริงต้องเปลี่ยนแปลง วิธีแก้ปัญหาในขั้นตอนการคอมไพล์คือการใช้การสืบทอด:
public class Format1ClassA extends ClassA { @Override public String getStringData () { return format ( toString ()); } }และอาจสร้างอ็อบเจ็กต์ที่มี "รูปแบบ" ที่ถูกต้องในระหว่างการทำงานโดยใช้รูปแบบโรงงาน (factory pattern )
โซลูชันอะแดปเตอร์รันไทม์
วิธีแก้ปัญหาโดยใช้ "อะแดปเตอร์" มีขั้นตอนดังนี้:
- กำหนดอินเทอร์เฟซ "ผู้ให้บริการ" ระดับกลาง และเขียนการใช้งานอินเทอร์เฟซผู้ให้บริการนั้น โดยให้อินเทอร์เฟซนี้ห่อหุ้มแหล่งข้อมูล
ClassAในตัวอย่างนี้ และส่งออกข้อมูลในรูปแบบที่เหมาะสม:อินเทอร์เฟซStringProvider { public String getStringData (); }ClassAFormat1 ระดับสาธารณะใช้StringProvider { ClassA ส่วนตัว= null ;ClassAFormat1 สาธารณะ( ClassA สุดท้ายa ) { classA = a ; }public String getStringData () { return format ( classA.getStringData ( ) ); }private String format ( final String sourceValue ) { // ปรับแต่งสตริงต้นฉบับให้เป็นรูปแบบที่ต้องการ// สำหรับวัตถุที่ต้องการข้อมูลจากวัตถุต้นฉบับreturn sourceValue . trim (); } }
- เขียนคลาสอะแดปเตอร์ที่ส่งคืนการใช้งานเฉพาะของตัวให้บริการ:
public class ClassAFormat1Adapter extends Adapter { public Object adapt ( final Object anObject ) { return new ClassAFormat1 (( ClassA ) anObject ); } }
- ลงทะเบียน
adapterกับระบบลงทะเบียนระดับโลก เพื่อให้adapterสามารถค้นหาได้ในระหว่างการทำงาน:AdapterFactory.getInstance ( ) . registerAdapter ( ClassA.class , ClassAFormat1Adapter.class , " format1 " ) ;
- ในโค้ด เมื่อต้องการถ่ายโอนข้อมูลจาก
ClassAที่หนึ่งไปยังอีกที่หนึ่งClassBให้เขียนดังนี้:Adapter adapter = AdapterFactory.getInstance ( ) . getAdapterFromTo ( ClassA.class , StringProvider.class , " format1 " ) ; StringProvider provider = ( StringProvider ) adapter.adapt ( classA ) ; String string = provider.getStringData ( ) ; classB.setStringData ( string ) ;
หรือกล่าวโดยย่อ:
classB.setStringData ( ( ( StringProvider ) AdapterFactory.getInstance ( ) . getAdapterFromTo ( ClassA.class , StringProvider.class , " format1 " ) . adapt ( classA ) ) . getStringData ( ) ) ;
- ข้อดีก็คือ หากต้องการถ่ายโอนข้อมูลในรูปแบบอื่น ก็สามารถค้นหาอะแดปเตอร์/ผู้ให้บริการที่แตกต่างกันได้:
Adapter adapter = AdapterFactory.getInstance ( ) . getAdapterFromTo ( ClassA.class , StringProvider.class , " format2 " ) ;
- และหากต้องการส่งออกข้อมูลเป็น
ClassAข้อมูลรูปภาพในรูปแบบใดรูปแบบหนึ่ง:ClassCAdapter adapter = AdapterFactory.getInstance ( ) . getAdapterFromTo ( ClassA.class , ImageProvider.class , " format2 " ) ; ImageProvider provider = ( ImageProvider ) adapter.adapt ( classA ) ; classC.setImage ( provider.getImage ( ) ) ;
- ด้วยวิธีนี้ การใช้อะแดปเตอร์และโพรวิเดนเซอร์ช่วยให้สามารถ "เข้าถึง" และ "ดู" ข้อมูลได้หลายแบบโดยไม่
ClassBต้องเปลี่ยนแปลงลำดับชั้นของคลาส โดยทั่วไปแล้ว วิธีนี้จะช่วยให้มีกลไกสำหรับการไหลเวียนของข้อมูลระหว่างอ็อบเจ็กต์ต่างๆ ได้อย่างอิสสระ ซึ่งสามารถปรับให้เข้ากับลำดับชั้นของอ็อบเจ็กต์ที่มีอยู่แล้วได้ClassCClassA
การนำรูปแบบอะแดปเตอร์ไปใช้
ในการใช้งานรูปแบบ Adapter เพื่อความชัดเจน เราสามารถใช้ชื่อคลาสกับส่วนการใช้งาน Provider ได้ เช่น ` <provider_name>` โดยควรมีเมธอด Constructor ที่รับตัวแปรคลาส Adaptee เป็นพารามิเตอร์ พารามิเตอร์นี้จะถูกส่งไปยังสมาชิกอินสแตนซ์ของ `<provider_name> ` เมื่อเมธอด ClientMethod ถูกเรียก จะสามารถเข้าถึงอินสแตนซ์ของ Adaptee ซึ่งจะช่วยให้เข้าถึงข้อมูลที่จำเป็นของ Adaptee และดำเนินการกับข้อมูลนั้นเพื่อสร้างผลลัพธ์ที่ต้องการได้ [ClassName]To[Interface]AdapterDAOToProviderAdapter[ClassName]To[Interface]Adapter
ชวา
แพ็คเกจorg.wikipedia.examples ;interface ILightningPhone { void recharge (); void useLightning (); }interface IMicroUsbPhone { void recharge (); void useMicroUsb (); }คลาสIphone implements ILightningPhone { private boolean connector ;@Override public void useLightning ( ) { connector = true ; System.out.println ( " Lightning connected " ) ; }@Override public void recharge ( ) { if ( connector ) { System.out.println ( " Recharge started" ) ; System.out.println ( " Recharge finished " ) ; } else { System.out.println ( " Connect Lightning first " ) ; } } }คลาสAndroid implements IMicroUsbPhone { private boolean connector ;@Override public void useMicroUsb () { connector = true ; System . out . println ( "MicroUsb connected" ); }@Override public void recharge ( ) { if ( connector ) { System.out.println ( " Recharge started" ) ; System.out.println ( " Recharge finished" ); } else { System.out.println ( " Connect MicroUsb first" ); } } } / * เปิดเผยอินเทอ ร์เฟซเป้าหมายขณะห่อหุ้ม วัตถุต้นทาง */ class LightningToMicroUsbAdapter implements IMicroUsbPhone { private final ILightningPhone lightningPhone ;public LightningToMicroUsbAdapter ( ILightningPhone lightningPhone ) { this . lightningPhone = lightningPhone ; }@Override public void useMicroUsb () { System . out . println ( "MicroUsb connected" ); lightningPhone . useLightning (); }@Override public void recharge () { lightningPhone.recharge ( ) ; } }public class AdapterDemo { static void rechargeMicroUsbPhone ( IMicroUsbPhone phone ) { phone . useMicroUsb (); phone . recharge (); }static void rechargeLightningPhone ( ILightningPhone phone ) { phone.useLightning ( ) ; phone.recharge ( ) ; }public static void main ( String [] args ) { Android android = new Android (); Iphone iPhone = new Iphone ();System.out.println ( " กำลัง ชาร์จAndroid ด้วยMicroUSB" ); rechargeMicroUsbPhone ( android );System.out.println ( " กำลังชาร์จiPhone ด้วย Lightning" ) ; rechargeLightningPhone ( iPhone );System.out.println ( " กำลัง ชาร์จiPhone ด้วย MicroUSB" ) ; rechargeMicroUsbPhone ( new LightningToMicroUsbAdapter ( iPhone )); } }เอาต์พุต
การชาร์จแอนดรอยด์ด้วย MicroUSB เชื่อมต่อผ่าน MicroUSB เริ่มการชาร์จแล้ว การชาร์จเสร็จสิ้น การชาร์จ iPhone ด้วยสาย Lightning สายฟ้าแลบ เริ่มการชาร์จแล้ว การชาร์จเสร็จสิ้น การชาร์จ iPhone ด้วย MicroUSB เชื่อมต่อผ่าน MicroUSB สายฟ้าแลบ เริ่มการชาร์จแล้ว การชาร์จเสร็จสิ้น
ไพธอน
""" ตัวอย่างรูปแบบ Adapter """ จากabc นำเข้าABCMeta , abstractmethod จากtyping นำเข้าNoReturnชาร์จ: รายการ[ str ] = [ "เริ่มชาร์จ" , "ชาร์จเสร็จสิ้น" ] อะแดปเตอร์ แปลงไฟ : พจนานุกรม[ str , str ] = { "Android" : "MicroUSB" , "iPhone" : "Lightning" } ข้อความเชื่อมต่อ: str = " {} เชื่อมต่อแล้ว" ข้อความเชื่อมต่อ ครั้งแรก : str = "เชื่อมต่อ{} ก่อน"class RechargeTemplate ( metaclass = ABCMeta ): @abstractmethod def recharge ( self ) -> NoReturn : raise NotImplementedError ( "คุณควรเขียนโค้ดส่วนนี้เอง" )class FormatIPhone ( RechargeTemplate ): @abstractmethod def use_lightning ( self ) -> NoReturn : raise NotImplementedError ( "คุณควรเขียนโค้ดส่วนนี้เอง" )class FormatAndroid ( RechargeTemplate ): @abstractmethod def use_micro_usb ( self ) -> NoReturn : raise NotImplementedError ( "คุณควรเขียนโค้ดส่วนนี้เอง" )คลาสiPhone ( FormatIPhone ): __name__ : str = "iPhone"def __init__ ( self ): self . connector : bool = Falsedef use_lightning ( self ) - > None : self.connector = True print ( CONNECTED_MSG.format ( POWER_ADAPTERS [ self .__ name__ ] ) )def recharge ( self ) -> None : if self . connector : for state in RECHARGE : print ( state ) else : print ( CONNECT_FIRST_MSG . format ( POWER_ADAPTERS [ self . __name__ ]))คลาสAndroid ( FormatAndroid ): __name__ : str = "Android"def __init__ ( self ) -> None : self . connector : bool = Falsedef use_micro_usb ( self ) - > None : self.connector = True print ( CONNECTED_MSG.format ( POWER_ADAPTERS [ self .__ name__ ] ) )def recharge ( self ) -> None : if self . connector : for state in RECHARGE : print ( state ) else : print ( CONNECT_FIRST_MSG . format ( POWER_ADAPTERS [ self . __name__ ]))คลาสIPhoneAdapter ( FormatAndroid ): def __init__ ( self , mobile : FormatAndroid ) -> None : self . mobile : FormatAndroid = mobiledef recharge ( self ) -> None : self . mobile . recharge ()def use_micro_usb ( self ) - > None : print ( CONNECTED_MSG.format ( POWER_ADAPTERS [ " Android " ] ) ) self.mobile.use_lightning ( )class AndroidRecharger : def __init__ ( self ) -> None : self . phone : Android = Android () self . phone . use_micro_usb () self . phone . recharge ()class IPhoneMicroUSBRecharger : def __init__ ( self ) -> None : self . phone : IPhone = IPhone () self . phone_adapter : IPhoneAdapter = IPhoneAdapter ( self . phone ) self . phone_adapter . use_micro_usb () self . phone_adapter . recharge ()class IPhoneRecharger : def __init__ ( self ) -> None : self . phone : IPhone = IPhone () self . phone . use_lightning () self . phone . recharge ()print ( "กำลังชาร์จ Android ด้วยที่ชาร์จ MicroUSB." ) AndroidRecharger () print ()print ( "กำลังชาร์จ iPhone ด้วย MicroUSB โดยใช้รูปแบบอะแดปเตอร์." ) IPhoneMicroUSBRecharger () print ()print ( "กำลังชาร์จ iPhone ด้วยที่ชาร์จ iPhone." ) IPhoneRecharger ()ซี#
เนมสเปซWikipedia.Examples ;โดยใช้ระบบ;interface ILightningPhone { void ConnectLightning (); void Recharge (); }interface IUsbPhone { void ConnectUsb (); void Recharge (); }sealed class AndroidPhone : IUsbPhone { private bool isConnected ;public void ConnectUsb () { this . isConnected = true ; Console . WriteLine ( "เชื่อมต่อโทรศัพท์ Android แล้ว" ); }public void Recharge ( ) { if ( this.isConnected ) { Console.WriteLine ( " กำลังชาร์จโทรศัพท์ Android" ); } else { Console.WriteLine ( " เสียบสาย USB ก่อน" ) ; } } }คลาสปิดผนึกApplePhone : ILightningPhone { private bool isConnected ;public void ConnectLightning ( ) { this.isConnected = true ; Console.WriteLine ( " Apple phone connected. " ) ; }public void Recharge () { if ( this.isConnected ) { Console.WriteLine ( " กำลังชาร์จโทรศัพท์ Apple" ) ; } else { Console.WriteLine ( " กรุณาเสียบสาย Lightning ก่อน" ) ; } } }sealed class LightningToUsbAdapter : IUsbPhone { private readonly ILightningPhone lightningPhone ;private bool isConnected ;public LightningToUsbAdapter ( ILightningPhone lightningPhone ) { this . lightningPhone = lightningPhone ; }public void ConnectUsb ( ) { this.lightningPhone.ConnectLightning ( ) ; }public void Recharge ( ) { this.lightningPhone.Recharge ( ) ; } }public class AdapterDemo { static void Main ( string [ ] args ) { ILightningPhone applePhone = new ApplePhone (); IUsbPhone adapterCable = new LightningToUsbAdapter ( applePhone ); adapterCable.ConnectUsb ( ); adapterCable.Recharge ( ) ; } }ผลลัพธ์:
โทรศัพท์ Apple เชื่อมต่อแล้วโทรศัพท์ Apple กำลังชาร์จดูเพิ่มเติม
- รูปแบบการออกแบบ Java สำหรับอะแดปเตอร์ - อะแดปเตอร์
- การมอบหมายอำนาจมีความเกี่ยวข้องอย่างมากกับรูปแบบอะแดปเตอร์วัตถุ
- หลักการผกผันการพึ่งพา (Dependency Inversion Principle ) ซึ่งอาจมองได้ว่าเป็นการประยุกต์ใช้รูปแบบอะแดปเตอร์ (Adapter Pattern) เมื่อคลาสระดับสูงกำหนดอินเทอร์เฟซ (อะแดปเตอร์) ของตนเองให้กับโมดูลระดับต่ำ (ซึ่งถูกนำไปใช้โดยคลาสเป้าหมาย)
- สถาปัตยกรรมพอร์ตและอะแดปเตอร์
- ชิม
- ฟังก์ชัน Wrapper
- ไลบรารี Wrapper
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ รูปแบบอะแดปเตอร์
ใน วิศวกรรมซอฟต์แวร์ รูป แบบอะแดปเตอร์ เป็น รูปแบบการออกแบบซอฟต์แวร์ (เรียกอีกอย่างว่า wrapper ซึ่งเป็นชื่อเรียกอีกชื่อหนึ่งที่ใช้ร่วมกับ รูปแบบเดโคเรเตอร์ ) ที่อนุญาตให้ใช้...
ภาพรวม
รูปแบบการออกแบบ อะแดปเตอร์ [ 2 ] เป็นหนึ่งใน 23 รูปแบบการออกแบบ Gang of Four ที่รู้จักกันดี ซึ่งอธิบายวิธีการแก้ปัญหาการออกแบบที่เกิดขึ้นซ้ำๆ เพื่อออกแบบซอฟต์แวร์เชิงวัตถุที่มีความยืดหยุ่นและนำกลับมาใช้ใหม่ได้ กล่าวคือ วัตถุที่ง่ายต่อการใช้งาน เปลี่ยนแปลง...
คำนิยาม
อะแดปเตอร์ช่วยให้สองอินเทอร์เฟซที่ไม่เข้ากันสามารถทำงานร่วมกันได้ นี่คือคำจำกัดความในโลกแห่งความเป็นจริงของอะแดปเตอร์ อินเทอร์เฟซอาจไม่เข้ากัน แต่ฟังก์ชันการทำงานภายในควรเหมาะสมกับความต้องการ...
การใช้งาน
สามารถใช้อะแดปเตอร์ได้เมื่อตัวห่อต้องเคารพอินเทอร์เฟซเฉพาะและต้องรองรับพฤติกรรมแบบ โพลีมอร์ฟิก ในทางกลับกัน รูปแบบตัวตกแต่ง ทำให้สามารถเพิ่มหรือเปลี่ยนแปลงพฤติกรรมของอินเทอร์เฟซในขณะรันไทม์ได้ และ รูปแบบฟาซาด...