Adaptor (model de design)
Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de
versiunea revizuită la 9 martie 2016; controalele necesită
47 de modificări .
Adaptor |
---|
Adaptor |
Adaptor de vizualizare a structurii șablonului |
Tip de |
structural |
Scop |
pentru a organiza utilizarea funcțiilor unui obiect care nu este disponibil pentru modificare printr-o interfață special creată (aduce interfața unei clase (sau a mai multor clase) la interfața de tipul dorit) |
Se aplică în cazuri |
sistemul acceptă datele și comportamentul necesar, dar are o interfață necorespunzătoare. Cea mai frecventă utilizare a modelului Adaptor este atunci când doriți să creați o clasă care derivă dintr-o clasă abstractă nou definită sau deja existentă. |
pro |
- încapsularea implementării claselor externe (componente, biblioteci), sistemul devine independent de interfața claselor externe;
- trecerea la utilizarea altor clase externe nu necesită reelaborarea sistemului în sine, este suficient să implementați o clasă Adapter.
|
Șabloane înrudite |
Fatada , Decorator |
Descris în Design Patterns |
da |
Adaptor ( eng. Adapter ) este un model de proiectare structural conceput pentru a organiza utilizarea funcțiilor unui obiect care nu este disponibil pentru modificare printr-o interfață special creată . Cu alte cuvinte, este un model de design structural care permite obiectelor cu interfețe incompatibile să lucreze împreună.
Caracteristici cheie
Provocare
Sistemul acceptă datele și comportamentul necesar, dar are o interfață inadecvată.
Soluție
Adaptorul prevede crearea unei clase de wrapper [1] cu interfața necesară.
Membrii
O clasă Adaptermapează o interfață de clasă Adapteela o interfață de clasă Target(care este implementată de clasă Adapter). Acest lucru permite obiectului să Clientfolosească obiectul Adaptee(prin adaptor Adapter) ca și cum ar fi o instanță a clasei Target.
Accesează astfel Clientinterfața Targetimplementată de clasa Adaptercare redirecționează apelul către Adaptee.
Consecințele
Modelul Adaptor permite ca obiectele existente să fie incluse în noi structuri de obiecte, indiferent de diferențele dintre interfețele lor.
Note și comentarii
Modelul Adaptor permite procesului de proiectare să ignore posibilele diferențe în interfețele claselor existente. Dacă există o clasă care are metodele și proprietățile necesare (cel puțin conceptual), atunci, dacă este necesar, puteți utiliza oricând modelul Adaptor pentru a-și aduce interfața la forma dorită.
Aproape de adaptor este modelul Fațadei , nu este întotdeauna posibil să se distingă unul de celălalt [2] .
Aplicarea unui șablon
Un exemplu tipic de utilizare a modelului Adaptor este crearea de clase care conduc la o singură interfață a unei funcții de limbaj PHP care oferă acces la diferite SGBD [3] .
O soluție la această problemă folosind șablonul Adaptor este prezentată în figură.
Implementare
Includerea unei clase deja existente într-o altă clasă. Interfața clasei incluse este actualizată pentru a îndeplini noile cerințe, iar apelurile la metodele sale sunt convertite în apeluri la metodele clasei incluse.
Etape de implementare
- Asigurați-vă că aveți două clase cu interfețe incompatibile:
- serviciu util - o clasă de utilitate pe care nu o poți modifica (este fie terță parte, fie alt cod depinde de ea);
- unul sau mai mulți clienți - clase de aplicații existente care sunt incompatibile cu serviciul din cauza unei interfețe incomode sau nepotrivite.
- Descrieți interfața client prin care clasele de aplicații ar putea folosi clasa de serviciu.
- Creați o clasă de adaptor prin implementarea acestei interfețe.
- Plasați un câmp în adaptor care va stoca o referință la obiectul de serviciu. De obicei, acest câmp este populat cu obiectul transmis constructorului adaptorului. În cazul adaptării simple, acest obiect poate fi trecut ca parametri la metodele adaptoare.
- Implementați toate metodele de interfață client în adaptor. Adaptorul trebuie să delege cea mai mare parte a lucrării serviciului.
- Aplicația ar trebui să utilizeze adaptorul numai prin interfața client. Acest lucru va facilita schimbarea și adăugarea adaptoarelor în viitor.
Ruby
Exemplu în
Ruby
module AdapterPattern
# Permite clientului să utilizeze Adaptees cu interfețe incompatibile prin Adaptoare cu interfață țintă
# Adaptee
clasa Twitter
def twit
pune „Twit a fost publicat” la
sfârșitul
sfârșitului
# Adaptee
clasa Facebook
def post
pune „Postarea Facebook a fost publicată” la
sfârșitul
sfârșitului
#
Modulul țintă WebServiceInterface
def send_message
raise NotImplementedError
end
end
#
Clasa adaptor TwitterAdapter
include WebServiceInterface
def initialize
@webservice = Twitter . sfârşit nou
def send_message
@webservice . Sfârșitul sfârșitului tweetului
# Clasa adaptor FacebookAdapter
include WebServiceInterface
def initialize
@webservice = Facebook . sfârşit nou
def send_message
@webservice . sfârșitul post -
sfârșit
#
Clasa client Mesaj
attr_accessor :webservice
def trimite
@webservice . send_message
end
end
def sine . run
puts '=> Adaptor'
mesaj = Mesaj . nou
mesaj . serviciu web = TwitterAdapter . mesaj nou . trimite
mesaj . webservice = FacebookAdapter . mesaj nou
. trimite
pune ''
end
end
AdaptorPattern . alerga
Java - moștenire
Exemplu
Java (prin moștenire)
// Target
public interface Chief
{
public Object makeBreakfast ();
public Object makeLunch ();
Public Object makeDinner ();
}
// Adaptee
public class Instalator
{
public Object getScrewNut ()
{ ... }
public Object getPipe ()
{ ... }
public Object getGasket ()
{ ... }
}
// Adaptor
public class ChiefAdapter se extinde Instalator implementa Chief
{
public Object makeBreakfast ()
{
return getGasket ();
}
public Object makeLunch ()
{
return getPipe ();
}
public Object makeDinner ()
{
return getScrewNut ();
}
}
// Client
public class Client
{
public static void eat ( Object dish )
{ ... }
public static void main ( String [] args )
{
Chief ch = new ChiefAdapter ();
Farfurie obiect = ch . faceMicul dejun (); mănâncă ( mâncare ); farfurie = ch . facePrânzul (); mănâncă ( mâncare ); farfurie = ch . faceCina (); mănâncă ( mâncare ); apelAmbulanță (); } }
Compoziția Java
Exemplu
Java (prin compoziție)
// Fișierul Chief.java
Șef interfață publică {
Public Object makeBreakfast ();
Public Object makeDinner ();
Public Object makeSupper ();
}
// Fișier Plumber.java
Instalator de clasă publică {
public Object getPipe () {
return new Object ();
}
public Object getKey () {
return new Object ();
}
public Object getScrewDriver () {
return new Object ();
}
}
// Fișierul ChiefAdapter.java
Clasa publică ChiefAdapter implementează Chief {
instalator instalator privat = instalator nou ();
@Override
public Object makeBreakfast () {
return plumber . getkey ();
}
@Override
public Object makeDinner () {
return instalator . getScrewDriver ();
}
@Override
public Object makeSupper () {
return instalator . getPipe ();
}
}
// Fișier client.java
clasă publică client {
public static void main ( String [] args ) {
Chief chief = new ChiefAdapter ();
Cheie obiect = cap . faceCina ();
}
}
scala
exemplu
Scala
adaptor obiect pachet {
obiect Battlefield {
protected var redTroops : Array [ Troop ] = Array ()
protected var blueTroops : Array [ Troop ] = Array ()
def addTroop ( trupă : Trupă ) : Unitate = {
dacă ( trupă . partea == " roșu " ) {
Trupe roșii :+= trupă
} else if ( trupă . parte == " albastru " ) {
Trupe albastre :+= trupă
} else {
aruncă o nouă excepție ( s"Partea invalidă ${ trupă . latură } pentru trupă ${ trupă . nume } " )
}
}
def getClosestEnemyTroop ( side : String ): Troop = {
if ( side == "red" ) {
getTroop ( blueTroops )
} else {
getTroop ( redTroops )
}
}
private def getTroop ( trupe : Array [ Troop ]): Troop = {
if ( trupe . lungime == 0 ) {
throw new Exception ( „Nu există trupe disponibile” )
}
trupe ( 0 )
}
}
clasa Trupa (
latura val : String , nume val : String , val closeWeapon : String , val distanceWeapon : String ) {
def mutare ( direcție : String , distanță : Int ): Unit = {
println ( s" Numele trupei $ mută $ direcție pe $ distanță metri " ) }
def attack ( enemyTroop : Troop , attackType : String ) : Unit = {
val weapon = attackType match {
case "distance" => distanceWeapon
case "close" => closeWeapon
case _ => arunca o nouă Excepție ( s"Tip de atac nevalid $ attackType pentru trupa $ nume " )
}
println ( s"Trupa $ name atacă trupa inamică ${ enemyTroop . name } cu ${ armele } lor" )
}
}
trăsătură LanceKnightTroopTrait {
def moveForward ( distanta : Int ) : Unit
def attackClosest ( attackType : String ) : Unit
}
clasa LanceKnightTroop (
override val side : String ,
override val name : String ,
override val closeWeapon : String ,
override val distanceWeapon : String
)
extinde Troop ( side , name , closeWeapon , distanceWeapon )
cu LanceKnightTroopTrait {
override def moveForward ( distanta : Int ): Unit = {
mutare ( " inainte " , distanta )
}
override def attackClosest ( attackType : String ): Unit = {
attack ( Battlefield . getClosestEnemyTroop ( side ), attackType )
}
}
obiect AdapterTest extinde AbstractTest {
override def run (): Unitate = {
val trupă = trupă nouă ( " albastru " , " Arcași " , " sabie " , " arc lung " ) val lanceKnightTroop = nou LanceKnightTroop ( " roșu " , " Lance Knights " , " știucă " , arbaleta )
Câmp de luptă . addTroop ( trupă ) Câmp de
luptă . addTroop ( lanceKnightTroop )
println ( "Ieșire:" )
lanceKnightTroop . mută înainte ( 300 )
lanceKnightTroop . atacClosest ( „închidere” )
}
}
}
// Ieșire:
// Troop Lance Knights înaintează cu 300 de metri
// Troop Lance Knights atacă arcașii trupei inamice cu stiuțele lor
PHP5
Exemplu în
PHP 5
<?php
class IndependentDeveloper1
{
public function calc ( $a , $b ) {
return $a + $b ;
}
}
class IndependentDeveloper2
{
public function nameIsVeryLongAndUncomfortable ( $a , $b ) {
return $a + $b ;
}
}
interfață IAdapter
{
public function sum ( $a , $b );
}
clasa ConcreteAdapter1 implementează IAdapter
{
protected $object ;
function public __construct () {
$this -> object = new IndependentDeveloper1 ();
}
public function sum ( $a , $b ) {
return $this -> object -> calc ( $a , $b );
}
}
clasa ConcreteAdapter2 implementează IAdapter
{
protected $object ;
public function __construct () {
$this -> object = new IndependentDeveloper2 ();
}
public function sum ( $a , $b ) {
return $this -> object -> nameIsVeryLongAndUncomfortable ( $a , $b );
}
}
// într-un singur loc creăm un adaptor concret și apoi folosim interfața
$adapter1 = new ConcreteAdapter1 ();
$adapter2 = nou ConcreteAdapter2 ();
/**
* Peste tot în cod nu folosim clase direct, dar prin interfață
* această funcție nu contează ce clasă folosim, deoarece ne bazăm pe interfața
*
* @param IAdapter $adapter
*/
function sum ( IAdapter $ adaptor ) {
echo $ adaptor -> suma ( 2 , 2 );
}
suma ( $adapter1 );
suma ( $adapter2 );
PHP5.4
Exemplu în
PHP 5.4 (trăsătură)
<?php
class SomeClass
{
public function someSum ( $a , $b )
{
return $a + $b ;
}
}
class AnotherClass
{
public function anotherSum ( $a , $b )
{
return $a + $b ;
}
}
caracteristica TAdaptee
{
public function sum ( int $a , int $b )
{
$metoda = $aceasta -> metoda ;
returnează $acest -> $metodă ( $a , $b );
}
}
clasa SomeAdaptee extinde SomeClass
{
folosește TAdaptee ;
private $method = 'someSum' ;
}
clasa AnotherAdaptee extinde AnotherClass
{
folosește TAdaptee ;
private $method = 'otherSum' ;
}
$ uni = nou SomeAdaptee ;
$altul = nou AnotherAdaptee ;
$uni -> suma ( 2 , 2 );
$altul -> suma ( 5 , 2 );
PHP5.4 Compact
Exemplu în
PHP 5.4 (Compact)
<?php
caracteristica TAdaptee
{
public function sum ( int $a , int $b )
{
$metoda = $aceasta -> metoda ;
returnează $acest -> $metodă ( $a , $b );
}
}
clasa SomeClass
{
folosește TAdaptee ;
private $method = 'someSum' ;
function public someSum ( $a , $b ) { return $a + $b ; } }
clasa AnotherClass
{
folosește TAdaptee ;
private $method = 'otherSum' ;
function public anotherSum ( $a , $b ) { return $a + $b ; } }
$ uni = nou SomeClass ;
$altul = nou AnotherClass ;
$uni -> suma ( 2 , 2 );
$altul -> suma ( 5 , 2 );
JavaScript
Exemplu
JavaScript
function Search ( text , word ) {
var text = text ;
var cuvânt = cuvânt ;
aceasta . searchWordInText = function () {
return text ;
};
aceasta . getWord = function () {
return word ;
};
};
function SearchAdapter ( adaptat ) {
this . searchWordInText = function () {
return 'Aceste cuvinte' + adaptee . getWord ()
+ ' găsit în text ' + adaptee . searchWordInText ();
};
};
var căutare = căutare nouă ( „text” , „cuvinte” ); var searchAdapter = nou SearchAdapter ( căutare ); searchAdapter . searchWordInText ();
Python
Exemplu în
Python
clasa GameConsole :
def create_game_picture ( self ):
returnează „imagine din consolă”
class Antena :
def create_wave_picture ( self ):
returnează „imagine din val”
clasa SourceGameConsole ( GameConsole ):
def get_picture ( self ):
return self . create_game_picture ()
clasa SourceAntenna ( Antena ):
def get_picture ( self ):
return self . create_wave_picture ()
clasa TV :
def __init__ ( self , source ):
self . sursă = sursă
def show_picture ( self ):
return self . sursa . 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# - compoziție
Exemplu
C# (compoziție)
folosind System ;
adaptor
pentru spațiu de nume {
class MainApp
{
static void Main ()
{
// Creați adaptor și plasați o solicitare
țintă țintă = adaptor nou (); tinta . cerere ();
// Așteptați
Consola utilizatorului . citește ();
}
}
// „Țintă”
class Target
{
public virtual void Solicitare ()
{
Consola . WriteLine ( "Called TargetRequest()" );
}
}
// „Adaptor”
class Adapter : Target
{
private Adaptee Adaptee = nou Adaptee ();
public override void Request ()
{
// Posibil să faceți o altă lucrare
// și apoi apelați SpecificRequest
adaptee . SpecificRequest ();
}
}
// „Adaptat”
class Adaptee
{
public void SpecificRequest ()
{
Console . WriteLine ( "Denumit SpecificRequest()" );
}
}
}
C# - moștenire
Exemplu
C# (moștenire)
folosind System ;
adaptor
pentru spațiu de nume {
class MainApp
{
static void Main ()
{
// Creați adaptor și plasați o cerere
Adaptor Adaptor = adaptor nou (); adaptor . cerere ();
// Așteptați
Consola utilizatorului . citește ();
}
}
// „Țintă”
interfață ITarget
{
public void Request ();
}
// Puteți folosi clasa abstractă
// „Adaptor”
class Adapter : Adaptee , ITarget
{
public void Request ()
{
// Posibil să faceți o altă lucrare
// și apoi apelați SpecificRequest
SpecificRequest ();
}
}
// „Adaptat”
class Adaptee
{
public void SpecificRequest ()
{
Console . WriteLine ( "Denumit SpecificRequest()" );
}
}
}
Delphi
exemplu
Delphi
adaptor de program;
{$APPTYPE CONSOLE}
{$R *.res}
utilizări
System.SysUtils;
(*Interfața de utilizare a clientului din clasa TTarget realizată ca TAdapter*)
(*TAdapter redirecționează apelul către TAdaptee*)
tip
TTarget = clasa
functionRequest:string; virtual;
Sfârşit;
TAdapte = clasa
funcția SpecificRequest:șir;
Sfârşit;
TAdapter = clasă (TTarget)
fAdaptee: TAdaptee;
functionRequest:string; trece peste;
constructorCreate;
Sfârşit;
{ TTarget }
funcția TTarget.Request: șir;
ÎNCEPE
Rezultat:= 'Called Target Request()';
Sfârşit;
{TAdaptee}
funcția TAdaptee.SpecificRequest: șir;
ÎNCEPE
Rezultat:= 'Denumit SpecificRequest()';
Sfârşit;
{TAdapter}
constructor TAdapter.Create;
ÎNCEPE
fAdaptee:= TAdaptee.Create;
Sfârşit;
funcția TAdapter.Request: șir;
ÎNCEPE
(*E posibil să faceți o altă lucrare și când sunați SpecificRequest*)
Rezultat:= fAdaptee.SpecificRequest;
Sfârşit;
var target: TTarget;
ÎNCEPE
încerca
{ TODO -oUser -cConsole Main : Inserați codul aici }
(*creează un adaptor și plasează o cerere*)
target:= TAdapter.Create;
WriteLn(target.Request);
WriteLn(#13#10+'Apăsați orice tastă pentru a continua...');
ReadLn;
target.Free;
cu exceptia
pe E: Excepție nu
Writeln(E.ClassName, ': ', E.Message);
Sfârşit;
Sfârşit.
Note
- ↑ Apropierea semnificațiilor termenilor shell și wrapper ( în engleză wrapper - folosit ca sinonim pentru un decorator) duce uneori la confuzie și Adapter este definit ca sinonim pentru șablonul Decorator , în timp ce acestea sunt două șabloane diferite, iar acesta din urmă. rezolvă o altă sarcină și anume: conectarea obligațiilor suplimentare la obiect.
- ↑ Diferența este că modelul Fațadă este conceput pentru a simplifica interfața, în timp ce modelul Adaptor este conceput pentru a aduce diverse interfețe existente la același aspect dorit.
- ↑ În versiunile învechite ale limbajului PHP, accesul la SGBD este implementat ca un set de funcții, pentru fiecare SGBD au nume diferite și, uneori, un set diferit de parametri utilizați, ceea ce duce la probleme semnificative la trecerea de la un SGBD la altul, dacă o astfel de tranziție nu este furnizată în prealabil folosind șablonul Adaptor.
Literatură
- Alan Shalloway, James R. Trott. Modele de design. O nouă abordare a designului orientat pe obiecte = Modelele de design explicate: O nouă perspectivă asupra designului orientat pe obiecte. - M . : „Williams” , 2002. - S. 288. - ISBN 0-201-71594-5 .
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tehnici de proiectare orientată pe obiecte. Design Patterns = Design Patterns: Elements of Reusable Object-Oriented Software. - Sankt Petersburg. : „Petru” , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (și ISBN 5-272-00355-1 )
- Eric Freeman, Elizabeth Freeman. Modele de design = Head First Design Patterns. - Sankt Petersburg. : Peter, 2011. - 656 p. - ISBN 978-5-459-00435-9 .
Link -uri