Vsebina
Adapter je strukturni načrtovalski vzorec, ki se uporablja za organizacijo in izvajanje metod objektov, ki jih ni mogoče spremeniti s posebej zasnovanim vmesnikom. Z drugimi besedami, to je strukturiran vzorec, ki omogoča medsebojno komunikacijo predmetov z nezdružljivimi vmesniki.
Opis
Vzorec Adapter izvaja prilagajanje med razredi in predmeti. Tako kot vsak adapter v svetu okoli nas je tudi predloga vmesnik ali most med dvema objektoma. V resničnem svetu imamo adapterje za napajalnike, trde diske, slušalke, pomnilniške kartice za fotoaparate itd. Za primer si oglejmo nekaj adapterjev za pomnilniške kartice. Če pomnilniške kartice fotoaparata ni mogoče priključiti neposredno na prenosni računalnik, lahko uporabite adapter: pomnilniška kartica fotoaparata je priključena na adapter, adapter pa je priključen v režo prenosnega računalnika. Na ta način bo rešena težava nezdružljivih vmesnikov.

V primeru razvoja programska oprema stvari so približno enake. Predstavljamo si lahko situacijo, ko obstaja razred, ki pričakuje neko vrsto objekta, in objekt, ki ponuja enako funkcionalnost, vendar z drugačnim vmesnikom. Seveda je koristno uporabljati oba vmesnika, da vam ni treba ponovno implementirati enega od vmesnikov in spreminjati obstoječih razredov. V tem primeru je smiselno uporabiti adapter za oblikovanje programske opreme.
Izvajanje
Spodnji diagram prikazuje diagram razredov vzorca UML (UML) Adapter.

Razredi in predmeti, vključeni v oblikovni vzorec:
- (Cilj - opredeljuje vmesnik za posamezno domeno, ki ga bo uporabljal odjemalec.
- (Adapter) - prilagodi vmesnik (Adaptee) ciljnemu vmesniku.
- (Prilagojenec) - opredeljuje obstoječi vmesnik, ki ga je treba prilagoditi.
- (odjemalec) - interakcija s predmeti, ki ustrezajo vmesniku (cilj).
Aplikacija
Vzorec Adaptee se uporablja v naslednjih primerih:
- Kadar obstaja razred (Target), ki kliče metode, opredeljene v vmesniku. Poleg tega obstaja še en razred (Adapter), ki ne implementira vmesnika, vendar implementira operacije in metode, ki se kličejo iz prvega razreda prek vmesnika. Programer ne more spremeniti nobene od obstoječih kod. Adapter implementira svoj vmesnik in postane most med razredoma.

- Pri pisanju razreda (Target) za splošno uporabo je pomembno, da se zanašamo na nekatere skupne vmesnike, razvijalec pa ima nekaj implementiranih razredov, ki ne implementirajo vmesnika. Ta razred (Target) mora biti tudi klicljiv.
Dober primer uporabe adapterja so lupine, ki se uporabljajo za sprejemanje knjižnic in struktur tretjih oseb: večina aplikacij, ki uporabljajo knjižnice tretjih oseb, uporablja adapter kot vmesno plast med aplikacijo in knjižnico tretje osebe, da se aplikacija loči od knjižnice. Ko je treba uporabiti drugo knjižnico, je potreben le adapter za novo knjižnico, ne da bi bilo treba spremeniti kodo aplikacije.
Adapterji za objekte na podlagi prenosa
Objekt (adapter) je klasičen primer vzorca adapterja. Uporablja kompozicijo in (Adaptee) delegira klice nase, kar ni na voljo adapterjem razredov, ki razširjajo (Adaptee). To vedenje nam daje več prednosti pred adapterji razredov, vendar lahko adapterje razredov implementiramo v jezikih, ki omogočajo večkratno dedovanje. Glavna prednost je, da (Adapter) ne prilagodi le (Adaptee), temveč tudi vse njegove podrazrede. Vsi ti podrazredi obstajajo z enim "majhno" omejitev: vsi ne morejo dodajati novih metod, ker se uporablja mehanizem delegiranja. Za vsako novo metodo je torej treba prilagoditi ali razširiti adapter, da bo omogočal nove metode. Glavna pomanjkljivost je, da je treba napisati novo kodo za prenos vseh potrebnih zahtev na adapter.
Adapterji razredov, ki temeljijo na (večkratnem) dedovanju
Adapterji razredov se lahko izvajajo v jezikih, ki podpirajo večkratno dedovanje. Programski jeziki Java, C# ali PHP ne podpirajo večkratnega dedovanja, imajo pa vmesnike. Zato takšnih vzorcev v teh jezikih ni mogoče enostavno implementirati. Dober primer programskega jezika, v katerem lahko preprosto izvedete načrtovanje, je C.
Vzorec Adapter namesto sestavljanja uporablja dedovanje. To pomeni, da namesto delegiranja klicev (Adaptee) podeduje. Na koncu mora celoten razred adapter imeti podrazred (Target) in samega sebe (Adapter).

S tem pristopom so lastne prednosti in slabosti:
- Vzorec prilagodi določen razred (Adaptee). Razred razširja to prilagoditev. Če gre za podrazred, ga ni mogoče prilagoditi z obstoječim adapterjem.
- Vzorec ne zahteva, da je vsa koda, potrebno za Delegacija, ki mora biti napisana za razred (adapter).
- Če je cilj predstavljen z vmesnikom in ne z razredom, lahko govorimo o "razred" ker lahko implementiramo poljubno število vmesnikov.
Dvostranski adapterji
Dvosmerni adapterji so adapterji, ki implementirajo tako (Target) kot (Adaptee). Prilagojeni predmet se lahko uporablja kot (Target) v novih sistemih, ki delajo z razredi (Target), ali kot (Adaptee) v drugi sistemi, delo z razredi (Adaptee). Če gremo v tej smeri še dlje, imamo lahko adapterje, ki implementirajo n vmesnikov in se prilagajajo n sistemom. Dvosmerne in n-smerne adapterje je težko izvajati v sistemih, ki ne podpirajo večkratnega dedovanja. Če mora adapter razširiti razred (Target), ne more razširiti drugega razreda, kot je (Adaptee), zato mora biti (Adaptee) vmesnik in vsi klici se lahko prenesejo z adapterja na objekt (Adaptee).

Če sta si razreda (Target) in (Adapter) podobna, mora adapter preprosto prenesti zahteve iz razreda (Target) v razred (Adapter), če pa si razreda (Target) in (Adaptee) nista podobna, mora adapter morda pretvoriti podatkovne strukture med njima in izvajati operacije, ki so potrebne za razred (Target), vendar niso izvedene v razredu (Adaptee).
Primer izvajanja
Recimo, da imamo razred (Ptica) z metodama fly () in makeSound (). In tudi razred (ToyDuck) z metodo Squeak (). Recimo, da nimamo veliko predmetov (ToyDuck) in želimo namesto njih uporabiti predmete (Bird). Ptice imajo podobno funkcionalnost, vendar implementirajo drug vmesnik, zato jih ne moremo uporabljati neposredno. Zato bomo uporabili vzorec adapterja. V tem primeru bo naš (odjemalec) (ToyDuck), (prilagajalec) pa (Bird). Spodaj je primer izvedbe vzorca Adaptee v Javi, ki je eden najpogostejših vzorcev Kako uporabljati bliskovni pogon.
interfaceBird{publicvoidfly();publicvoidmakeSound();}classSparrowimplementsBird{publicvoidfly(){System.out.println("Flying");}publicvoidmakeSound(){System.out.println("Chirp Chirp");}}interfaceToyDuck{publicvoidsqueak();}classPlasticToyDuckimplementsToyDuck{publicvoidsqueak(){System.out.println("Squeak");}}classBirdAdapterimplementsToyDuck{Bird bird;publicBirdAdapter(Bird bird){this.bird = bird;}publicvoidsqueak(){bird.makeSound();}}classMain{publicstaticvoidmain(String args[]){Sparrow sparrow =newSparrow();ToyDuck toyDuck =newPlasticToyDuck();ToyDuck birdAdapter =newBirdAdapter(sparrow);System.out.println("Vrabec...");vrabec.muha();vrabec.makeSound();Sistem.iz.println("ToyDuck...");toyDuck.piskanje();Sistem.iz.println("BirdAdapter...");birdAdapter.piskanje();}}
Recimo, da imamo ptico, ki zna narediti Sound (), in plastično igračo račko, ki zna piskati - Squeak (). Predpostavimo, da naš (naročnik) spremeni zahtevo in želi, da (ToyDuck) izvede funkcijo Sound (), vendar kot?

Rešitev je, da preprosto spremenimo izvedbeni razred v novi razred adapterja in odjemalcu povemo, naj temu razredu posreduje primerek ptice. Začeli smo. S spremembo ene vrstice lahko (ToyDuck) naučimo čivkati kot vrabec.