In het laatste artikel hebben we gekeken hoe het ontwerppatroon van de gevel kan worden gebruikt om het gebruik van een groot en complex systeem te vereenvoudigen met alleen een eenvoudige gevelklasse.
In dit artikel zullen we onze discussie over ontwerppatronen voortzetten door een kijkje te nemen in de adapter ontwerppatroon. Dit specifieke patroon kan worden gebruikt wanneer uw code afhankelijk is van een externe API of een andere klasse die vaak wordt gewijzigd. Dit patroon valt onder de categorie 'structurele patronen' omdat het ons leert hoe onze code en onze klassen moeten worden gestructureerd om ze gemakkelijk te beheren en / of uit te breiden.
Nogmaals, ik wil herhalen dat ontwerppatronen niets nieuws zijn ten opzichte van traditionele klassen. In plaats daarvan laten ze ons een betere manier zien om onze klassen te structureren, hun gedrag aan te pakken en hun creatie te beheren.
sendPayment ( '2629');
In de bovenstaande code kunt u zien dat we een PayPal-klasse gebruiken om eenvoudig het bedrag te betalen. Hier maken we rechtstreeks het object van de PayPal-klasse en betalen we via PayPal. Je hebt deze code verspreid over meerdere plaatsen. Dus we kunnen zien dat de code de $ paypal-> sendPayment ('bedrag hier');
methode om te betalen.
Enige tijd geleden heeft PayPal de naam van de API-methode gewijzigd van stuur de betaling
naar payAmount
. Dit zou duidelijk een probleem moeten aangeven voor degenen onder ons die de stuur de betaling
methode. Concreet moeten we alles veranderen stuur de betaling
methode oproepen naar payAmount
. Stel je de hoeveelheid code voor die we moeten veranderen en de tijd die we moeten besteden aan het opnieuw testen van alle functies.
Een oplossing voor dit probleem is het gebruik van het ontwerppatroon van de adapter.
Volgens Wikipedia:
In de software-engineering is het adapterpatroon een softwareontwerppatroon waarmee de interface van een bestaande klasse kan worden gebruikt vanuit een andere interface. Het wordt vaak gebruikt om bestaande klassen met anderen te laten werken zonder hun broncode te wijzigen.
In dit geval moeten we een wrapper-interface maken die dit mogelijk maakt. We zullen geen wijzigingen in de externe klassenbibliotheek aanbrengen omdat we er geen controle over hebben en deze kan op elk moment veranderen.
Laten we nu in de code graven, die het adapterpatroon in actie toont:
// Beton Implementatie van PayPal Klasse klasse PayPal publieke functie __construct () // Uw code hier // openbare functie sendPayment ($ bedrag) // Betalen via Paypal // echo "Betalen via PayPal:". $ Bedrag; // Eenvoudige interface voor elke adapter die we interfacebetalingen makenAdapter openbare functie betalen ($ bedrag); class paypalAdapter implementeert paymentAdapter private $ paypal; publieke functie __construct (PayPal $ paypal) $ dit-> paypal = $ paypal; openbare functie betalen ($ bedrag) $ dit-> paypal-> sendPayment ($ bedrag);
Bestudeer de bovenstaande code en u zou moeten kunnen vertellen dat we geen wijzigingen hebben aangebracht in de hoofdtekst PayPal
klasse. In plaats daarvan hebben we één interface gemaakt voor onze betaaladapter en één adapterklasse voor PayPal.
En zo hebben we daarna het object van de adapterklasse gemaakt in plaats van de hoofdklasse PayPal
klasse. Terwijl we een object van adapterklasse maken, zullen we het object van de main passeren PayPal
class als een argument, zodat de adapterklasse een verwijzing naar de hoofdklasse kan hebben en de vereiste methoden van de hoofdklasse kan oproepen PayPal
klasse.
Laten we kijken hoe we deze methode rechtstreeks kunnen gebruiken:
// Klantcode $ paypal = nieuwe paypalAdapter (nieuwe PayPal ()); $ Paypal-> pay ( '2629');
Stel je nu voor dat PayPal de methode verandert van stuur de betaling
te betalen. Dan hoeven we alleen maar wijzigingen aan te brengen paypalAdapter
. Kijk maar eens naar de herziene adaptercode, die maar één verandering heeft.
klasse paypalAdapter implementeert paymentAdapter private $ paypal; publieke functie __construct (PayPal $ paypal) $ dit-> paypal = $ paypal; openbare functie betalen ($ bedrag) $ this-> paypal-> payAmount ($ bedrag);
Dus slechts één verandering en we zijn er.
Op dit moment hebben we gezien hoe we de adapter-patten kunnen gebruiken om de bovengenoemde scenario's te omzeilen. Nu is het heel eenvoudig om een nieuwe klasse toe te voegen, afhankelijk van de bestaande adapter. Laten we zeggen dat de MoneyBooker-API beschikbaar is voor betaling.
In plaats van rechtstreeks de MoneyBooker-klasse te gebruiken, zouden we hetzelfde adapterpatroon moeten toepassen dat we net voor PayPal hebben gebruikt.
// Concrete implementatie van MoneyBooker Klasse klasse MoneyBooker publieke functie __construct () // Uw code hier // openbare functie doPayment ($ bedrag) // Betalen via MoneyBooker // echo "Betalen via MoneyBooker:". $ Bedrag; // MoneyBooker Adapterklasse moneybookerAdapter implementeert paymentAdapter private $ moneybooker; openbare functie __construct (MoneyBooker $ moneybooker) $ this-> moneybooker = $ moneybooker; openbare functie betalen ($ bedrag) $ this-> moneybooker-> doPayment ($ bedrag); // Clientcode $ moneybooker = nieuwe moneybookerAdapter (nieuwe MoneyBooker ()); $ Moneybooker-> pay ( '2629');
Zoals je kunt zien, zijn dezelfde principes van toepassing. U definieert een methode die beschikbaar is voor klassen van derden en vervolgens, als een afhankelijkheid de API wijzigt, wijzigt u eenvoudig de afhankelijke klasse zonder de externe interface bloot te leggen.
Een geweldige applicatie is constant verslaafd aan andere bibliotheken en API's, dus ik zou voorstellen dat we de adaptermethode implementeren, zodat we geen problemen ondervinden wanneer een API of bibliotheek van derden de codebasis verandert.
Ik heb mijn best gedaan om een elementair en toch handig voorbeeld te geven om het ontwerppatroon van de adapter te demonstreren, maar als u aanvullende opmerkingen of vragen heeft, aarzel dan niet om deze in de onderstaande feed toe te voegen.