Internet Windows Android

Cod gata pentru adaptoare în java. Șabloane structurale: Adaptor

Adaptor este un model structural care vă permite să vă faceți prieteni între obiecte incompatibile.

Adaptorul acționează ca un strat între două obiecte, transformând apelurile de la unul în apeluri de înțeles pentru celălalt.

Caracteristicile modelului în Java

Complexitate:

Popularitate:

Aplicabilitate: Modelul poate fi găsit adesea în codul Java, mai ales acolo unde este necesară conversia diferitelor tipuri de date sau colaborarea claselor cu interfețe diferite.

Exemple de adaptoare din bibliotecile standard Java:

  • java.io.InputStreamReader(InputStream) (returnează un obiect Reader)
  • java.io.OutputStreamWriter(OutputStream) (returnează un obiect Writer)
  • javax.xml.bind.annotation.adapters.XmlAdapter#marshal() și #unmarshal()

Semne de utilizare a unui model: Adaptorul primește obiectul pentru a fi convertit în constructor sau prin parametrii metodelor sale. Metodele adaptoarelor sunt de obicei compatibile cu o interfață cu un singur obiect. Ei deleg apelurile unui obiect imbricat prin conversia mai întâi a parametrilor apelului într-un format acceptat de obiectul imbricat.

Plasarea cuielor pătrate în găuri rotunde

Acest exemplu simplu arată cum folosind modelul Adaptor puteți combina lucruri incompatibile.

rundă

round/RoundHole.java: gaura rotunda

pachet site.adapter.example.round; /** * RoundHole este compatibil cu RoundPegs. */ public class RoundHole ( rază dublă privată; public RoundHole ( rază dublă) ( this.radius = radius; ) public double getRadius() ( rază returnată; ) public boolean fits(RoundPeg peg) ( rezultat boolean; rezultat = (acest. getRadius() >= peg.getRadius());

round/RoundPeg.java: Cuie rotundă

pachet site.adapter.example.round; /** * RoundPegs sunt compatibile cu RoundHoles. */ public class RoundPeg ( rază dublă privată; RoundPeg public () () public RoundPeg ( rază dublă) ( this.radius = radius; ) public double getRadius() ( rază de întoarcere; ) )

pătrat

square/SquarePeg.java: Cuie pătrată

pachet site.adapter.example.square; /** * Cuiele pătrate sunt incompatibile cu găurile rotunde (au fost lăsate în proiect * după foștii dezvoltatori). Dar trebuie să le integrăm cumva în sistemul nostru *. */ public class SquarePeg ( private double width; public SquarePeg(double width) ( this.width = width; ) public double getWidth() ( return width; ) public double getSquare() ( dublu rezultat; rezultat = Math.pow(this .width, 2);

adaptoare

adaptoare/SquarePegAdapter.java: Adaptor știfturi pătrate la găuri rotunde

pachet site.adapter.exemplu..adaptor.exemplu.rotund..adaptor.exemplu.pătrat.SquarePeg; /** * Adaptorul vă permite să utilizați împreună chei pătrați și găuri rotunde. */ public class SquarePegAdapter extinde RoundPeg ( private SquarePeg peg; public SquarePegAdapter(SquarePeg peg) ( this.peg = peg; ) @Override public double getRadius() ( dublu rezultat; // Calculați raza minimă în care se va potrivi acest peg. rezultat = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2));

Demo.java: Cod client

site-ul pachetului.adapter..adaptator.exemplu.adaptoare..adaptor.exemplu.rotund..adaptor.exemplu.rotund..adaptor.exemplu.pătrat.SquarePeg; /** * Undeva în codul client... */ public class Demo ( public static void main(String args) ( // Round to round - totul funcționează. RoundHole hole = new RoundHole(5); RoundPeg rpeg = new RoundPeg (5); if (hole.fits(rpeg)) ( System.out.println("Rond peg r5 fits round hole r5."); ) SquarePeg smallSqPeg = new SquarePeg(2); smallSqPeg); // Adaptorul va rezolva problema. ) (System.out.println("Celul pătrat w20 nu se potrivește în gaura rotundă r5.") ; ) ) )

OutputDemo.txt: Rezultatul executiei

Cuie rotundă r5 se potrivește cu orificiul rotund r5. Cuie pătrată w2 se potrivește cu gaura rotundă r5. Șeful pătrat w20 nu se potrivește în gaura rotundă r5.

Adaptor / Wrapper.

Tip

Model de proiectare structurală.

Descriere

Șablonul Adaptor este conceput pentru a aduce interfața obiect la forma necesară.

Acest șablon este utilizat dacă:

  • un obiect existent, numit adaptabil, care oferă funcționalitatea necesară, dar nu suportă interfața necesară;
  • (sau) nu se știe dinainte cu ce interfețe va trebui să lucreze obiectul care urmează să fie adaptat;
  • (sau) formatul datelor de intrare sau de ieșire a metodei nu se potrivește cu cel cerut.

Sarcina principală a adaptorului este să implementeze interfața necesară și să își difuzeze apelurile către obiectul care este adaptat. O situație similară poate fi întâlnită atunci când se utilizează biblioteci terțe. Ele nu oferă întotdeauna interfețele necesare pentru a comunica cu alte obiecte. Cu toate acestea, nu este posibil să schimbați codul sau să adăugați suport pentru interfață.

Un alt caz de utilizare este ilustrat prin conectarea modulelor de expansiune. Să presupunem că există o componentă gata făcută care îndeplinește funcțiile necesare, dar nu știe nimic despre interfața necesară pentru utilizare. Adaptorul, în acest caz, va juca rolul unui adaptor pentru conectarea la interfața sistemului de extensie. În același timp, conectarea de noi componente poate schimba funcționalitatea aplicației.

Un alt exemplu de utilizare a unui model este adaptarea comportamentului. Această abordare este utilizată, de exemplu, în .NET atunci când lucrați cu obiecte COM: coduri de eroare primite de la acestea din valori de tip HRESULT este convertit pentru a arunca excepții de tip COMExcepții.

Astfel, scopul adaptorului este de a oferi posibilitatea de a reutiliza codul existent, indiferent de diferențele de interfață sau comportament. În plus, prin schimbarea obiectelor adaptabile este posibilă influențarea funcțiilor efectuate în program.

Există patru roluri atribuite obiectelor care participă la șablon:

  1. Adaptee obiect (Adaptee);
  2. Target, care definește interfața necesară;
  3. Adaptor;
  4. Un Client care poate lucra numai cu obiecte care implementează interfața țintă.

Trebuie luate în considerare următoarele puncte:

  1. Un adaptor nu trebuie să conțină doar apeluri către obiectul care este adaptat. Poate procesa datele de intrare și de ieșire, aducându-le la formatul dorit.
  2. În cadrul unui șablon, puteți utiliza mai multe obiecte adaptabile pentru a implementa o anumită interfață.
  3. Implementarea șablonului poate adăuga în mod independent funcționalitatea necesară dacă obiectul care este adaptat nu o are.
  4. Un adaptor poate funcționa nu numai cu un obiect adaptabil dat, ci și cu descendenții săi.
  5. Este posibilă înlocuirea unora dintre metodele obiectului care se adaptează. În acest caz, este necesar să se creeze o subclasă în care să se facă înlocuirile necesare. Și utilizați rezultatul în adaptor.
  6. Implementarea adaptorului poate fi bidirecțională. În acest caz, obiectul adaptabil implementează logica intermediară pentru a conecta două obiective, fiecare dintre ele necesită propria interfață.
  7. Puteți folosi Lazy Initialization pentru a instanția un obiect adaptabil.

Modele similare și diferențele lor

Adaptor Schimbă interfața unui obiect fără a-i schimba funcționalitatea. Poate adapta mai multe obiecte la o singură interfață. Vă permite să reutilizați codul existent. Conține sau moștenește obiectul adaptabil.
Faţadă Unește un grup de obiecte sub o singură interfață specializată. Simplifică lucrul cu un grup de obiecte și introduce un nou nivel de abstractizare. Conține sau face referire la obiecte necesare implementării unei interfețe specializate.
Pod Separă un obiect în abstractizare și implementare. Folosit pentru ierarhia obiectelor. Vă permite să modificați (moșteniți) separat abstracția și implementarea, crescând flexibilitatea sistemului. Conține un obiect (implementare) care furnizează metode pentru o anumită abstracție și rafinamentele acesteia (moștenitori).
Decorator Extinde capacitățile unui obiect și schimbă comportamentul acestuia. Acceptă interfața obiectelor decorabile, dar poate adăuga noi metode și proprietăți. Vă permite să schimbați dinamic funcționalitatea unui obiect. Este o alternativă la moștenire (inclusiv multiplă). Conține obiectul de decorat. Este posibil un lanț de obiecte numite secvenţial.
Proxy Înlocuiește în mod transparent un obiect și controlează accesul la acesta. Nu schimbă interfața sau comportamentul. Simplificați și optimizați lucrul cu obiectul. Poate adăuga propria sa funcționalitate, ascunzând-o de client. Conține un obiect sau o referință la acesta și poate controla existența unui obiect înlocuit.
Linker Oferă o singură interfață pentru interacțiunea cu obiectele compozite și părțile acestora. Simplifică munca clientului și facilitează adăugarea de noi variante de obiecte compozite și părți ale acestora. Inclus ca interfață în obiectele compozite și părțile acestora.
Oportunist

Nu are ca scop schimbarea interfeței obiectului. Dar acest lucru poate fi necesar pentru a recupera date din partea extrasă a statului.

Vă permite să reduceți numărul de instanțe de obiect din aplicație și, prin urmare, să economisiți resursele acesteia. Externalizează partea sensibilă la context a stării unui obiect, înlocuind mai multe instanțe ale acestuia cu una.

Implementarea șablonului în formă generală

Conform schemei folosite pentru a lucra cu un obiect adaptabil, există două opțiuni:

  1. Adaptor de obiect – folosește compoziția, de ex. conține o instanță a obiectului adaptabil.
  2. Adaptor de clasă - Utilizează moștenirea de la obiectul care este adaptat pentru a obține funcționalitatea acestuia.

Prima variantă are prioritate, pentru că oferă mai puțină cuplare la obiectul care se adaptează. În acest caz, poate chiar converti o interfață la alta fără a fi legat de o implementare specifică.

Dar există situații în care este necesară utilizarea unui adaptor de clasă. De exemplu, necesitatea de a accesa metode protejate. Într-un alt caz, poate fi necesar să utilizați un adaptor în loc de un obiect adaptabil.

Implementarea unui adaptor de obiecte

  • creați o clasă ITarget sau fii moștenitor dintr-o clasă Ţintă cu interfața necesară;
  • în câmpul său închis _adaptat plasați o instanță a obiectului adaptabil;
  • implementează interfața ITarget

Implementarea unui adaptor de clasă

  • creați o clasă , care va implementa interfața necesară ITarget;
    • șablonul vă permite să utilizați moștenirea clasei Ţintă, dar această opțiune nu poate fi implementată în C#. Motivul este interzicerea moștenirii multiple.
  • adăugând la clasă moștenire dintr-o clasă adaptabilă;
  • implementează interfața ITarget, în metodele cărora le numim metodele necesare obiectului în curs de adaptare;
  • clientul folosește o instanță a clasei și obține funcționalitatea necesară.

Exemple de implementare

1. Adaptor obiect

Provocare: Aplicația trebuie să redea semnale sonore pentru a alerta utilizatorul, care sunt stocate în prezent în format .wav.

Interfață IAudioPlayer conține o descriere a funcțiilor celui mai simplu player media care descarcă și redă un fișier audio.

///

Încarcă fișierul audio. void Load(fișier șir); /// Redă fișierul audio. void Play(); )

Când implementați, vă rugăm să rețineți că .NET conține deja clasa SoundPlayer, care oferă capabilități similare. Cu toate acestea, această clasă nu acceptă interfața specificată. Prin urmare, vom folosi șablonul Adaptor:

///

Interfață simplă pentru player audio. SoundPlayerAdapter de clasă publică: IAudioPlayer ( /// Obiect adaptat. privat numai leneș _lazyPlayer = nou Leneș (); /// Încarcă fișierul audio. public void Load(fișier șir) ( this._lazyPlayer.Value.SoundLocation = fișier; this._lazyPlayer.Value.Load(); ) /// Redă fișierul audio. public void Play() ( this._lazyPlayer.Value.Play(); ) )

Codul este foarte simplu. Puteți observa doar utilizarea Lazy Initialization (folosind clasa generică Leneş) pentru clasa în curs de adaptare. Acest lucru se face în cazul în care nu sunt descărcate sau redate fișiere audio.

Acum este posibil să utilizați funcțiile SoundPlayerîn aplicația în curs de dezvoltare:

Private IAudioPlayer _player = nou SoundPlayerAdapter(); public void NotifyUser(int messageCode) ( string wavFile = string.Empty; /* Sarit */ // redă fișierul audio dacă (!string.IsNullOrEmpty(wavFile)) ( this._player.Load(wavFile); this._player. Joaca();

Poate apărea întrebarea: de ce să nu folosiți imediat clasa SoundPlayer? Spre deosebire de utilizarea explicită a clasei specificate, această abordare a asigurat independența codului față de implementarea specifică a playerului media. De exemplu, în viitor puteți înlocui cu ușurință SoundPlayerAdapter la altă clasă pentru a suporta fișiere de alt format.

2. Adaptor de clasă

Să ne uităm la rezolvarea aceleiași probleme folosind un adaptor de clasă.

De data aceasta este necesar să moștenești SoundPlayerAdapter nu numai din interfață IAudioPlayer, dar și de la clasă SoundPlayer. Ca rezultat, obținem o metodă gata făcută Joaca(), și aici este metoda Sarcină() va trebui să o determinați singur.

///

Interfață simplă pentru player audio. SoundPlayerAdapter de clasă publică: SoundPlayer, IAudioPlayer ( /// Încarcă fișierul audio. public void Load(fișier șir) ( this.SoundLocation = fișier; this.Load(); ) )

Ce s-a schimbat față de prima versiune?

Inițializarea întârziată a obiectului adaptabil, care în prima versiune era „din cutie” și transparent pentru codul clientului, a dispărut.

Codul de implementare a devenit mai scurt, deoarece A trebuit să creez doar metodele lipsă. Este posibil ca clasa Adaptor să nu conțină niciun cod. De exemplu:

///

Interfață simplă pentru player audio. interfață publică IAudioPlayer ( /// Obține sau setează calea fișierului sau adresa URL a fișierului .wav de încărcat. string SoundLocation ( obține; setează; ) /// Încarcă fișierul audio. void Load(); /// Redă fișierul audio. void Play(); ) /// Interfață simplă pentru player audio. clasa publică SoundPlayerAdapter2: SoundPlayer, IAudioPlayer()

În plus, o instanță a clasei SoundPlayerAdapter acum oferă o listă completă de proprietăți și metode moștenite din obiectul care se adaptează. Poate fi folosit în loc de exemplu SoundPlayer daca este necesar. Dar merită să ne amintim că în acest caz legătura dintre obiectul care se adaptează și codul aplicației este întărită. Și acesta este cel mai mare dezavantaj al acestei opțiuni.

    Articolul principal: Adaptor (model de proiectare) Un exemplu de implementare a unui model în C# folosind System; Adaptor de spațiu de nume ( clasa MainApp ( static void Main() ( ... Wikipedia

    Acest termen are alte semnificații, vezi Model. În dezvoltarea de software, un model de design sau un model de design este un design arhitectural repetabil care reprezintă o soluție la o problemă... ... Wikipedia

    Model de proiectare a interfeței Interfață descrisă în modelele de proiectare Nu În informatică, modelul de interfață nu este un model special printre modelele de design. Este o metodă generală de structurare a programelor de calculator pentru a... Wikipedia

    Model de design proxy. Oferă un obiect de control al accesului, interceptând toate apelurile către acesta. Cuprins 1 Scop 1.1 Problemă 1.2 Soluție 2 Pro 3 ... Wikipedia

    Design Pattern Guardian Memento Tip: Comportamental Descris în Design Patterns Da Guardian (cunoscut și sub numele de Memento, Token, Token) este un model de design comportamental. Vă permite să reparați fără a întrerupe încapsularea... Wikipedia

    Design Pattern Iterator Iterator Tip: Comportamental Descris în Design Patterns Da Iterator Pattern (cunoscut și ca Cursor) Un model de design care se referă la modele comportamentale. Este un obiect care vă permite să obțineți... Wikipedia

    Model de proiectare Tip de interpret: comportamental Scop: rezolvă o problemă care apare frecvent, predispusă la schimbare Descris în Modele de proiectare Da Model de interpret (în engleză ... Wikipedia

    Model de design Tip compozit: structural Descris în Modele de proiectare Da Modelul compozit este un model de design, se referă la modele structurale, combină un obiect... Wikipedia

    Tipul de stare a modelului de proiectare: comportamental Descris în modelele de proiectare Da Starea este un model de proiectare. Este folosit în cazurile în care, în timpul execuției programului, un obiect... Wikipedia

Să revenim la luarea în considerare a modelelor de proiectare structurală. De data aceasta ne vom uita la un model de design numit Adaptor(se mai numește și Wrapper împreună cu modelul Fațade).

În acest articol vom vorbi despre următoarele:

Deci, modelul Adaptor este folosit astfel încât obiectele cu o singură interfață (contract) să poată funcționa acolo unde este nevoie de un obiect cu o interfață complet diferită. Există două tipuri de adaptoare - adaptor de clasă și adaptor de obiect.

În primul rând, ne vom uita la fiecare dintre aceste tipuri, apoi voi explica diferența dintre cele două ambalaje - adaptor și fațadă.

Adaptor de obiecte

Object Adapter își atinge scopul prin compoziție. În diagrama de mai jos, clientului i se cere să utilizeze interfața TargetInterface. Pentru a face acest lucru, este creată o clasă ObjectAdapter care implementează interfața TargetInterface și, de asemenea, stochează un obiect de clasă Adaptee. Când se apelează metoda targetMethod de pe adaptor, este apelată metoda corespunzătoare de pe interfața care se adaptează.

În cel mai simplu caz, implementarea ObjectAdapter ar fi astfel:

Clasa publică ObjectAdapter implementează TargetInterface (adaptat privat Adaptee; public void targetMethod() ( adaptee.method() ) )

Avantajul acestei abordări este că separăm complet interfața client de interfața adaptabilă.

Adaptor de clasă

În cazul Class Adapter, moștenirea multiplă este utilizată pentru a ne atinge scopul nostru ClassAdapter moștenește din interfața client și din interfața Adaptable Deoarece nu există o moștenire multiplă în Java, doar unul dintre strămoși poate fi o clasă abstractă/concretă Al doilea strămoș va fi interfața, ceea ce nu este întotdeauna convenabil.

Diagrama de clasa:

Și iată o implementare trivială a clasei ClassAdapter:

Clasa publică ClassAdapter extinde Adaptee implementează TargetInterface ( public void targetMethod() ( method(); ) )

Aș dori să vă atrag atenția asupra faptului că, cu o astfel de implementare a adaptorului, poate apărea un conflict în semnăturile metodei. Object Adapter nu are această problemă.

Class Adapter este considerat o soluție mai simplă atunci când nu este necesară separarea strictă a interfețelor client și adaptabile.

Diferența dintre adaptor și fațadă

Acum vreau să spun câteva cuvinte despre modelul Facade, care, ca și adaptorul, este un Wrapper definit nou interfață în timp ce adaptorul este utilizat existent interfețe.

Nu ar trebui să comparați Facade și Adapter astfel: se spune că Facade poate îngloba mai multe clase, dar Adapter adaptează doar una. Se poate foarte bine ca adaptorul să fie necesar pentru a adapta mai multe clase și invers, Fațada va trebui folosită pentru a simplifica doar o clasă complexă. Deci diferența dintre aceste două modele nu este în numărul de entități care sunt înfășurate, ci în motivul pentru care o fac.

Exemplu de utilizare a adaptorului în JDK

De asemenea, puteți găsi exemple de utilizare a adaptorului în biblioteca standard. Probabil cel mai popular caz de utilizare este java.io.InputStreamReader și OutputStreamWriter.

Constructorul InputStreamReader ia un InputStream ca intrare și ca rezultat adaptează fluxul în Reader.

Mai târziu voi posta codul pentru utilizarea adaptoarelor din proiecte reale la care am participat, dar deocamdată aștept întrebările și comentariile voastre. Noroc.

    Adaptor (model de proiectare)/Exemple de cod- Articolul principal: Adaptor (model de proiectare) Un exemplu de implementare a unui model în C# folosind System; Adaptor pentru spațiu de nume ( clasa MainApp ( static void Main() ( ... Wikipedia

    Model proxy (model de design)

    Model de design- Acest termen are alte semnificații, vezi Model. În dezvoltarea de software, un model de design este un design arhitectural repetabil care reprezintă o soluție la o problemă... ... Wikipedia

    Interfață (model de design)- Interfața modelului de design descrisă în modelele de proiectare Nu În informatică, modelul de interfață nu este un model special printre modelele de design. Este o metodă generală de structurare a programelor de calculator pentru a... Wikipedia

    Adjunct (model de proiectare)- Proxy Pattern (Deputat) Model de design. Oferă un obiect de control al accesului, interceptând toate apelurile către acesta. Cuprins 1 Scop 1.1 Problemă 1.2 Soluție 2 Pro 3 ... Wikipedia

    Guardian (model de design)- Design Pattern Guardian Memento Tip: Comportamental Descris în Design Patterns Da Guardian (cunoscut și sub numele de Memento, Token, Token) este un model de design comportamental. Vă permite să reparați fără a întrerupe încapsularea... Wikipedia

    Iterator (model de proiectare)- Design Pattern Iterator Iterator Tip: comportamental Descris în Design Patterns Da Iterator Pattern (cunoscut și ca Cursor) Un model de design care se referă la modele comportamentale. Este un obiect care vă permite să obțineți... Wikipedia

    Interpret (model de proiectare)- Model de proiectare Tip de interpret: comportamental Scop: rezolvă o problemă care apare frecvent, predispusă la schimbare Descris în Modele de proiectare Da Model de interpret (în engleză ... Wikipedia

    Linker (model de design)- Model de design Tip compozit: structural Descris în Modele de proiectare Da Modelul compozit este un model de design, se referă la modele structurale, combină un obiect... Wikipedia

    Stare (model de proiectare)- Model de design de stat Tip: comportamental Descris în modele de proiectare Da State este un model de design. Este folosit în cazurile în care, în timpul execuției programului, un obiect... Wikipedia