Adapter (tervezési minta)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2016. március 9-én felülvizsgált verziótól ; az ellenőrzések 47 szerkesztést igényelnek .
Adapter
Adapter

Sablon szerkezet nézet adapter
Típusú szerkezeti
Célja egy nem módosítható objektum funkcióinak használatának megszervezése egy speciálisan kialakított felületen keresztül (egy osztály (vagy több osztály) felületét hozza a kívánt típusú felületre)
esetekben érvényes a rendszer támogatja a szükséges adatokat és viselkedést, de nem megfelelő felülettel rendelkezik. Az Adapter minta legáltalánosabb használata az, amikor egy újonnan definiált vagy már meglévő absztrakt osztályból származó osztályt akarunk létrehozni.
profik
  • külső osztályok (komponensek, könyvtárak) megvalósításának beágyazása, a rendszer függetlenné válik a külső osztályok interfészétől;
  • más külső osztályok használatára való átállás nem igényli magának a rendszernek az átdolgozását, elég egy osztályt megvalósítani Adapter.
Kapcsolódó sablonok Homlokzat , lakberendező
Leírása: Tervezési minták Igen

Az Adapter ( angol.  Adapter ) egy szerkezeti tervezési minta , amely egy olyan objektum funkcióinak használatának megszervezésére szolgál, amely nem módosítható egy speciálisan létrehozott interfészen keresztül . Más szóval, ez egy olyan szerkezeti tervezési minta, amely lehetővé teszi az inkompatibilis interfésszel rendelkező objektumok együttműködését.

Főbb jellemzők

Kihívás

A rendszer támogatja a szükséges adatokat és viselkedést, de nem megfelelő felülettel rendelkezik.

Megoldás

Az adapter lehetővé teszi egy burkoló osztály [1] létrehozását a szükséges interfésszel.

Tagok

Egy osztály Adapterleképez egy osztályinterfészt Adapteeegy osztályinterfészre Target(amelyet az osztály valósít meg Adapter). Ez lehetővé teszi az objektum számára, hogy úgy Clienthasználja az objektumot Adaptee(az adapteren keresztül Adapter), mintha az az osztály egy példánya lenne Target.

Így hozzáfér az osztály által megvalósított Clientinterfészhez , amely átirányítja a hívást a -ra . TargetAdapterAdaptee

Következmények

Az Adapter minta lehetővé teszi a meglévő objektumok új objektumstruktúrákba való beillesztését, az interfészeik különbségeitől függetlenül.

Megjegyzések és megjegyzések

Az Adapter minta lehetővé teszi, hogy a tervezési folyamat figyelmen kívül hagyja a meglévő osztályok interfészeinek lehetséges különbségeit. Ha van egy osztály, amely rendelkezik a szükséges metódusokkal és tulajdonságokkal (legalábbis fogalmilag), akkor szükség esetén az Adapter mintával mindig a kívánt formába hozhatja a felületét.

Az Adapterhez közel áll a Homlokzati minta , nem mindig lehet megkülönböztetni az egyiket a másiktól [2] .

Sablon alkalmazása

Az Adapter minta használatának tipikus példája olyan osztályok létrehozása, amelyek egy PHP nyelvi függvény egyetlen interfészéhez vezetnek, amely hozzáférést biztosít különböző DBMS -ekhez [3] .

A probléma megoldása az Adapter sablon használatával az ábrán látható.

Megvalósítás

Egy másik osztályba már meglévő osztály belefoglalása. A befoglaló osztály interfésze az új követelményeknek megfelelően frissül, metódusainak hívásai pedig a benne foglalt osztály metódusainak hívásaivá alakulnak.


A megvalósítás lépései

  1. Győződjön meg arról, hogy két osztálya nem kompatibilis interfészekkel:
    • hasznos szolgáltatás - egy segédprogram osztály, amelyet nem tud megváltoztatni (vagy harmadik féltől származik, vagy más kód attól függ);
    • egy vagy több kliens - olyan meglévő alkalmazásosztályok, amelyek a szolgáltatással nem kompatibilisek egy kényelmetlen vagy nem egyező felület miatt.
  2. Írja le azt a kliens felületet, amelyen keresztül az alkalmazásosztályok használhatják a szolgáltatási osztályt.
  3. Hozzon létre egy adapterosztályt ennek az interfésznek a megvalósításával.
  4. Helyezzen el egy mezőt az illesztőben, amely a szolgáltatásobjektumra mutató hivatkozást tárolja. Ezt a mezőt általában az illesztő konstruktorának átadott objektum tölti ki. Egyszerű adaptáció esetén ez az objektum paraméterként átadható az adapter metódusoknak.
  5. Valamennyi kliens interfész metódust implementálja az adapterben. Az illesztőnek a munka nagy részét a szolgáltatásra kell delegálnia.
  6. Az alkalmazás csak a kliens felületen keresztül használja az adaptert. Ez megkönnyíti az adapterek cseréjét és hozzáadását a jövőben.


Ruby

Példa Rubyban modul AdapterPattern # Lehetővé teszi az ügyfél számára, hogy nem kompatibilis interfésszel rendelkező Adaptereket használjon Adapters with Target felülettel # Alkalmazkodó osztály A Twitter def twit a " Twit megjelent" végére helyezi # Alkalmazkodó osztály A Facebook def - bejegyzése a „Facebook-bejegyzés közzététele” végére kerül # Célmodul WebServiceInterface def send_message emelés NotImplementedError end end # Adapter osztály A TwitterAdapter tartalmazza a WebServiceInterface felületet def inicializál @webservice = Twitter . új vég def send_message @webservice . tweet vége vége # Adapterosztály A FacebookAdapter tartalmazza a WebServiceInterface felületet def inicializál @webservice = Facebook . új vég def send_message @webservice . post end end # Ügyfélosztály Üzenet attr_accessor : webservice def send @webservice . send_message end end def self . a run '=> Adapter' üzenet = Üzenet . új üzenetet . webszolgáltatás = TwitterAdapter . új üzenet . Küld üzenetet . webszolgáltatás = FacebookAdapter . új üzenet . Küld véget tesz AdapterPattern . fuss

Java - öröklődés

Java példa (öröklés útján) // Cél nyilvános felület Chief { public Object makeBreakfast (); public Object makeLunch (); public Object makeDinner (); } // Adaptee public class Plumber { public Object getScrewNut () { ... } public Object getPipe () { ... } public Object getGasket () { ... } } // Adapter public class ChiefAdapter expands Plumber implements Chief { public Object makeBreakfast ( ) { return getGasket (); } public Object makeLunch () { return getPipe (); } public Object makeDinner () { return getScrewNut (); } } // Client public class Kliens { public static void eat ( Object dish ) { ... } public static void main ( String [] args ) { Chief ch = new ChiefAdapter (); Tárgytál = ch . _ készítsen reggelit (); eszik ( tál ); edény = ch . készíts ebédet (); eszik ( tál ); edény = ch . makeDinner (); eszik ( tál ); mentőhívás (); } }

Java összetétel

Java példa (kompozíción keresztül) // Chief.java fájl nyilvános felület vezető { public Object makeBreakfast (); public Object makeDinner (); public Object makeSupper (); } // Plumber.java fájl public class vízvezeték-szerelő { public Object getPipe () { return new Object (); } public Object getKey () { return new Object (); } public Object getScrewDriver () { return new Object (); } } // ChiefAdapter.java fájl public class ChiefAdapter implementálja a Chief { privát Vízvezeték- szerelő = új Vízvezeték-szerelő (); @Override public Object makeBreakfast () { return plumber . getkey (); } @Override public Object makeDinner () { return plumber . getScrewDriver (); } @Override public Object makeSupper () { return plumber . getPipe (); } } // Client.java fájl public class kliens { public static void main ( String [] args ) { Chief chief = new ChiefAdapter (); Tárgykulcs = fej . _ makeDinner (); } }

scala

Scala példa csomagobjektum adapter { _ object Battlefield { védett var redTroops : Array [ Troop ] = Array () védett var blueTroops : Array [ Troop ] = Array () def addTroop ( csapat : Csapat ) : Egység = { if ( csapat . oldal == "piros" ) { redTroops :+= csapat } else if ( csapat . oldal == "kék" ) { blueTroops :+= csapat } else { throw new Exception ( s"Érvénytelen oldal ${ troop . side } for troop ${ troop . name } " ) } } def getClosestEnemyTroop ( oldal : String ): Csapat = { if ( side == "red" ) { getTroop ( blueTroops ) } else { getTroop ( redTroops ) } } privát def getTroop ( csapatok : Array [ Csapat ]): Csapat = { if ( csapatok . hossz == 0 ) { dob új Kivétel ( " Nincs elérhető csapat" } csapatok ( 0 ) } } class Csapat ( val oldal : String , val név : String , val closeFegyver : String , val távolságFegyver : String ) { def move ( irány : Karakterlánc , távolság : Int ): Unit = { println ( s"A csapat $ neve $ irányt mozog $ távolság yardon " ) } en _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ csapathoz $ name " ) } println ( s"A csapat $ név megtámadja az ellenséges csapatot ${ enemyTroop . name } $ { fegyver } fegyvereikkel " } } vonás LanceKnightTroopTrait { def moveForward ( távolság : Int ) : Egység def attackClosest ( attackType : String ) : Unit } class LanceKnightTroop ( override val side : String , override val name : String , override val closeWeapon : String , override val distance Weapon : String ) kiterjeszti a csapatot ( side , name , closeWeapon , distanceWeapon ) with LanceKnightTroopTrait { override def moveForward ( távolság : Int ): Egység = { mozgás ( "előre" , távolság ) } def attackClosest ( attackType : String ) felülbírálása : Unit = { attack ( Battlefield . getClosestEnemyTroop ( side ), attackType ) } } object AdapterTest extends AbstractTest { override def run (): Egység = { val troop = új csapat ( "kék" , "íjászok" , "kard" , "hosszúíj" ) val lanceKnightTroop = new LanceKnightTroop ( "piros" , "Lance Knights" , "csuka" " , számszeríj ) Battlefield . addTroop ( csapat ) Battlefield . addTroop ( lanceKnightTroop ) println ( "Kimenet:" ) lanceKnightTroop . moveForward ( 300 ) lanceKnightTroop . attackClosest ( "close" ) } } } // Kimenet: // A Troop Lance Knights 300 yardon halad előre // A Troop Lance Knights megtámadja az ellenséges csapat íjászait csukáikkal

PHP5

Példa PHP 5 -ben <?php class IndependentDeveloper1 { public function calc ( $a , $b ) { return $a + $b ; } } class IndependentDeveloper2 { public function nameIsVeryLongAnduncomfortable ( $a , $b ) { return $a + $b ; } } interface IAdapter { public function sum ( $a , $b ); } class ConcreteAdapter1 implements IAadapter { protected $object ; public function __construct () { $this -> object = new IndependentDeveloper1 (); } public function sum ( $a , $b ) { return $this -> object -> calc ( $a , $b ); } } class ConcreteAdapter2 implements IAdapter { protected $object ; public function __construct () { $this -> object = new IndependentDeveloper2 (); } public function sum ( $a , $b ) { return $this -> object -> nameIsVeryLongAndUncomfortable ( $a , $b ); } } //egy helyen készítünk egy betonadaptert, majd a $adapter1 = new ConcreteAdapter1 (); $adapter2 = új ConcreteAdapter2 (); /** * A kódban mindenhol nem közvetlenül használunk osztályokat, hanem az interfészen keresztül * ez a függvény nem mindegy, hogy melyik osztályt használjuk, mivel az interfészre támaszkodunk * * @param IAdapter $adapter */ függvény összege ( IAdapter $ adapter ) { echo $ adapter -> sum ( 2 , 2 ); } összeg ( $adapter1 ); összeg ( $adapter2 );

PHP5.4

Példa a PHP 5.4-ben (Trait) <?php class SomeClass { public function someSum ( $a , $b ) { return $a + $b ; } } class AnotherClass { public function otherSum ( $a , $b ) { return $a + $b ; } } trait TAdaptee { public function sum ( int $a , int $b ) { $method = $this -> method ; return $this -> $method ( $a , $b ); } } class SomeAdaptee extends SomeClass { use TAdaptee ; privát $method = 'someSum' ; } class AnotherAdaptee expands AnotherClass { use TAdaptee ; private $method = 'másikSum' ; } $some = new SomeAdaptee ; $egyéb = new AnotherAdaptee ; $néhány -> összeg ( 2 , 2 ); $másik -> összeg ( 5 , 2 );

PHP5.4 Compact

Példa PHP 5.4-ben (Compact) <?php trait TAdaptee { public function sum ( int $a , int $b ) { $method = $this -> method ; return $this -> $method ( $a , $b ); } } class SomeClass { use TAdaptee ; privát $method = 'someSum' ; public function someSum ( $a , $b ) { return $a + $b ; } } class AnotherClass { use TAdaptee ; private $method = 'másikSum' ; public function otherSum ( $a , $b ) { return $a + $b ; } } $some = új SomeClass ; $egyéb = új AnotherClass ; $néhány -> összeg ( 2 , 2 ); $másik -> összeg ( 5 , 2 );

JavaScript

JavaScript példa function Keresés ( szöveg , szó ) { var text = szöveg ; var szó = szó ; ezt . searchWordInText = function () { return text ; }; ezt . getWord = function () { return word ; }; }; function SearchAdapter ( adaptee ) { this . searchWordInText = function () { return 'Ezek a szavak' + adaptee . getWord () + ' szövegben található ' + adaptee . searchWordInText (); }; }; var search = new Keresés ( "szöveg" , "szavak" ); var searchAdapter = new SearchAdapter ( keresés ); searchAdapter . searchWordInText ();

Python

Példa Pythonban class GameConsole : def create_game_picture ( self ): 'kép a konzolról' visszaadása osztály Antenna : def create_wave_picture ( self ): return 'kép hullámból' osztály SourceGameConsole ( GameConsole ): def get_picture ( self ): return self . Create_game_picture () osztály ForrásAntenna ( Antenna ): def get_picture ( self ): return self . Create_wave_picture () osztály TV : def __init__ ( self , source ): self . forrás = forrás def show_picture ( self ): önmagát adja vissza . forrás . get_picture () g = SourceGameConsole () a = SourceAntenna () game_tv = TV ( g ) cabel_tv = TV ( a ) print ( game_tv . show_picture ()) print ( cabel_tv . show_picture ())

C# - kompozíció

C# példa (összetétel) a rendszer használatával ; névtér adapter { class MainApp { static void Main () { // Adapter létrehozása és kérés elhelyezése Target target = new Adapter (); cél . kérés (); // Várja meg a felhasználói konzolt . olvasni (); } } // "Cél" class Cél { public virtual void Kérelem () { Konzol . WriteLine ( "Called TargetRequest()" ); } } // "Adapter" class Adapter : Cél { private Adaptee adaptee = new Adaptee (); public override void Request () { // Esetleg végezzen más munkát //, majd hívja meg a SpecificRequest adaptee-t . SpecificRequest (); } } // "Adaptee" class Adaptee { public void SpecificRequest () { Console . WriteLine ( "Called SpecificRequest()" ); } } }

C# - öröklődés

C# példa (öröklődés) a rendszer használatával ; névtér adapter { class MainApp { static void Main () { // Adapter létrehozása és kérés elhelyezése Adapter adapter = new Adapter (); adapter . kérés (); // Várja meg a felhasználói konzolt . olvasni (); } } // "Cél" interface ITarget { public void Kérelem (); } // Használhat absztrakt osztályt // "Adapter" class Adapter : Adaptee , ITarget { public void Request () { // Esetleg végezzen más munkát //, majd hívja meg a SpecificRequest SpecificRequest (); } } // "Adaptee" class Adaptee { public void SpecificRequest () { Console . WriteLine ( "Called SpecificRequest()" ); } } }

Delphi

Delphi példa program adapter; {$APPTYPE CONSOLE} {$R *.res} használ System.SysUtils; (*A TTarget osztály kliens felhasználói felülete TAdapterként valósult meg*) (*TAdapter átirányítja a hívást a TAdaptee-ra*) típus TTarget = osztály functionRequest:string; virtuális; vége; TAdapte = osztály függvény SpecificRequest:string; vége; TAdapter = osztály (TTcél) fAdaptee: TAdaptee; functionRequest:string; felülírás; konstruktorCreate; vége; { TCél } függvény TTarget.Request: string; kezdődik Eredmény:= 'Called Target Request()'; vége; {TAdaptee} function TAdaptee.SpecificRequest: string; kezdődik Eredmény:= 'Speciális kérés()'; vége; {TAadapter} konstruktor TAdapter.Create; kezdődik fAdaptee:= TAdaptee.Create; vége; függvény TAdapter.Request: string; kezdődik (*Esetleg más munkát is végezhet, és amikor hívja a SpecificRequest*) Eredmény:= fAdaptee.SpecificRequest; vége; var target: TTarget; kezdődik próbálja meg { TODO -oUser -cConsole Main : Írja be ide a kódot } (*adapter létrehozása és kérés benyújtása*) target:= TAdapter.Create; WriteLn(cél.Kérés); WriteLn(#13#10+'Nyomja meg bármelyik gombot a folytatáshoz...'); ReadLn; cél.Ingyenes; kivéve E-n: Kivétel igen Writeln(E.Osztálynév, ': ', E.Üzenet); vége; vége.

Jegyzetek

  1. A shell és wrapper ( angolul  wrapper - a dekorátor szinonimájaként használt) kifejezések jelentésének közelsége néha zavarhoz vezet, és az Adaptert a Dekorátor sablon szinonimájaként definiálják , míg ez két különböző sablon és az utóbbi más feladatot old meg, nevezetesen: többletkötelezettségek objektumhoz kapcsolása.
  2. A különbség az, hogy a Homlokzati mintát az interfész egyszerűsítésére tervezték, míg az Adapter mintát arra tervezték, hogy a különböző meglévő interfészek ugyanazt a kívánt megjelenést hozzák.
  3. A PHP nyelv elavult verzióiban a DBMS-hez való hozzáférést függvénykészletként valósítják meg, minden DBMS-nek más neve van, és néha eltérő paraméterkészletet használnak, ami jelentős problémákhoz vezet az egyik DBMS-ről való váltáskor. egy másikat, ha az Adapter sablon segítségével előre nem biztosítanak ilyen átmenetet.

Irodalom

  • Alan Shalloway, James R. Trott. Tervezési minták. Az objektum-orientált tervezés új megközelítése = Design Patterns Explained: Új perspektíva az objektum-orientált tervezéshez. - M . : "Williams" , 2002. - S. 288. - ISBN 0-201-71594-5 .
  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Objektumorientált tervezés technikái. Tervezési minták = Design Patterns: Az újrafelhasználható objektum-orientált szoftver elemei. - Szentpétervár. : "Péter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . ( ISBN 5-272-00355-1 is )
  • Eric Freeman, Elizabeth Freeman. Tervezési minták = Head First Design Patterns. - Szentpétervár. : Péter, 2011. - 656 p. - ISBN 978-5-459-00435-9 .

Linkek