Modele de proiectare modelul adaptorului

În ultimul articol, am analizat modul în care poate fi folosit modelul de proiectare a fațadelor pentru a simplifica folosirea oricărui sistem vast și complex folosind doar o clasă de fațadă simplă. 

În acest articol, vom continua discuția noastră cu privire la modelele de design, luând o privire la modelul adaptorului de design. Acest model particular poate fi folosit atunci când codul dvs. depinde de un anumit API extern sau de orice altă clasă care este susceptibilă să se schimbe frecvent. Acest model se încadrează în categoria "modelelor structurale", deoarece ne învață cum ar trebui structurat codul și clasele noastre pentru a le gestiona și / sau extinde cu ușurință.

Din nou, aș dori să reiterez că modelele de design nu au nimic nou față de clasele tradiționale. În schimb, ele ne arată o modalitate mai bună de a structura clasele noastre, de a le gestiona comportamentul și de a le gestiona creația.

Problema

sendPayment ( '2629');

În codul de mai sus, puteți vedea că folosim o clasă PayPal pentru a plăti pur și simplu suma. Aici, creăm direct obiectul clasei PayPal și plătim prin PayPal. Aveți acest cod împrăștiat în mai multe locuri. Așa că putem vedea că codul folosește codul $ paypal-> sendPayment ("suma aici"); metodă de plată. 

Cu ceva timp în urmă, PayPal a schimbat numele metodei API Trimite plata la payAmount. Acest lucru ar trebui să indice în mod clar o problemă pentru cei dintre noi care au folosit Trimite plata metodă. Mai exact, trebuie să schimbăm totul Trimite plata apeluri metodă la payAmount. Imaginați-vă cantitatea de cod pe care trebuie să o modificăm și timpul pe care trebuie să-l cheltuim pentru testarea din nou a fiecărei caracteristici.

Soluția

O soluție la această problemă este utilizarea modelului de design al adaptorului. 

Potrivit Wikipedia:

În ingineria software, modelul de adaptor este un model de design software care permite interfeței unei clase existente să fie utilizată de la o altă interfață. Este adesea folosit pentru a face clasele existente să lucreze cu alții fără a modifica codul sursă.

În acest caz, ar trebui să creați o interfață de împachetare care să facă acest lucru posibil. Nu vom face modificări în biblioteca de clasă externă, deoarece nu avem control asupra acesteia și se poate schimba oricând. 

Să scriem acum codul, care arată modelul de adaptor în acțiune:

// Implementarea concretă a clasei PayPal Clasa de clasă PayPal funcția publică __construct () // Codul tău aici funcția publică sendPayment (suma $) // Plata prin Paypal // echo "Plata prin PayPal:". suma $;  // Interfață simplă pentru fiecare Adaptor pe care îl creăm pentru interfața de platăAdapter plată publică funcție (suma $);  clase paypalAdapter implements paymentAdapter private $ paypal; funcția publică __construct (PayPal $ paypal) $ this-> paypal = $ paypal;  plata funcției publice (suma $) $ this-> paypal-> sendPayment (suma $); 

Studiați codul de mai sus și ar trebui să știți că nu am introdus modificări în principalele PayPal clasă. În schimb, am creat o interfață pentru adaptorul nostru de plată și o clasă de adaptor pentru PayPal.

Și așa, după aceea am făcut obiectul clasei adaptorului în locul principalului PayPal clasă. În timp ce creăm un obiect de clasă adaptor, vom trece obiectul principalului PayPal clasa ca argument, astfel încât clasa adaptor poate avea o referință la clasa principală și poate apela metodele necesare ale principalului PayPal clasă.

Hai să aflăm cum putem folosi această metodă direct:

// Cod client $ paypal = new paypalAdapter (noul PayPal ()); $ Paypal-> cu plată ( '2629');

Acum imaginați-vă că PayPal își schimbă numele metodei Trimite plata la plataAmount. Atunci trebuie să facem schimbări paypalAdapter. Trebuie doar să aruncați o privire asupra codului adaptat revizuit, care are doar o singură modificare.

clasa paypalAdapter implementează plata Adapter private $ paypal; funcția publică __construct (PayPal $ paypal) $ this-> paypal = $ paypal;  funcția publică plătească (suma $) $ this-> paypal-> payAmount (suma $); 

Deci, doar o schimbare și suntem acolo.

Adăugarea unui nou adaptor

În acest moment, am văzut cum putem folosi adaptorul de design pentru a depăși scenariile menționate mai sus. Acum, este foarte ușor să adăugați o clasă nouă în funcție de adaptorul existent. Să presupunem că API-ul MoneyBooker este acolo pentru plată.

Apoi, în loc să folosim direct clasa MoneyBooker, ar trebui să aplicăm același model de adaptor pe care tocmai l-am folosit pentru PayPal.

// Implementarea concretă a MoneyBooker de clasă MoneyBooker funcția publică __construct () // Codul tău aici funcția publică doPayment (suma $) // Plătiți prin MoneyBooker // echo "Plata prin intermediul MoneyBooker:". suma $;  // Adaptorul MoneyBooker clasa moneybookerAdapter implementează plata Adapter private $ moneybooker; funcția publică __construct (MoneyBooker $ moneybooker) $ this-> moneybooker = $ moneybooker;  funcția publică plătească (suma $) $ this-> moneybooker-> doPayment (suma $);  // Cod client $ moneybooker = new moneybookerAdapter (noul MoneyBooker ()); $ Moneybooker-> cu plată ( '2629');

După cum puteți vedea, se aplică aceleași principii. Definiți o metodă disponibilă pentru clasele terțe și apoi, dacă o dependență își modifică API-ul, pur și simplu schimbați clasa dependentă fără a expune interfața externă.

Concluzie

O aplicație excelentă este în mod constant cuplată în alte biblioteci și API-uri, așadar aș propune implementarea metodei adaptorului, astfel încât să nu avem probleme când un API sau o bibliotecă terță parte modifică baza de cod.

Am încercat tot ce pot pentru a oferi un exemplu elementar și totuși util pentru a demonstra modelul de design al adaptorului, dar dacă aveți comentarii sau întrebări suplimentare, vă rugăm să nu ezitați să le adăugați în fluxul de mai jos.

Cod