Cod gata pentru adaptoare în java. Model de design adaptor

    Articolul principal: Adaptor (model de proiectare) Exemplu de implementare a modelului în C# folosind System; Adaptor pentru 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 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 stochează, de asemenea, 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.

Scop

Adaptor(Engleză) Adaptor sau engleză Înveliș-Wrapper) este un model de design structural conceput pentru a organiza utilizarea funcțiilor unui obiect care nu este disponibil pentru modificare printr-o interfață special creată.

Sarcină

Sistemul acceptă datele și comportamentul necesar, dar are o interfață necorespunzătoare.

Soluţie

Adaptorul prevede crearea unei clase de wrapper cu interfața necesară.

Participanții

Clasa Adapter mapează interfața clasei Adaptee cu interfața clasei Ţintă(din care Adapter este un succesor). Acest lucru permite obiectului Client să folosească obiectul Adaptee (prin Adaptor) ca și cum ar fi o instanță a clasei Ţintă.

În acest fel, Clientul accesează interfața Ţintă, implementat în succesorul lui Adapter, care redirecționează apelul către Adaptee.

Diagrama de clasă UML a modelului Adaptor

Consecințe

Modelul Adaptor vă permite să încorporați obiecte existente în noi structuri de obiecte, indiferent de diferențele dintre interfețele lor.

Descriere

Lăsați clasa a cărei interfață trebuie adaptată la forma dorită să fie numită Adaptee. Pentru a rezolva problema transformării interfeței, modelul Adaptor introduce următoarea ierarhie de clase:

    Clasa de bază virtuală țintă. Aici este declarată o interfață de utilizator de tipul adecvat. Numai această interfață este disponibilă utilizatorului.

    O clasă derivată de Adaptor care implementează interfața țintă. Această clasă conține, de asemenea, un pointer sau o referință la o instanță Adaptee. Modelul Adaptor folosește acest indicator pentru a redirecționa apelurile client către Adaptee. Deoarece interfețele Adaptee și Target sunt incompatibile între ele, aceste apeluri necesită de obicei conversie.

Modelul Adaptor, care este un pachet de software peste clasele existente, convertește interfețele acestora într-o formă potrivită pentru utilizarea ulterioară.

Să ne uităm la un exemplu simplu de când trebuie utilizat modelul Adaptor. Să dezvoltăm un sistem de control al climei conceput pentru a menține automat temperatura ambientală în limitele specificate. O componentă importantă a unui astfel de sistem este un senzor de temperatură, care măsoară temperatura ambiantă pentru analiza ulterioară. Pentru acest senzor, există deja software gata făcut de la dezvoltatori terți, care este o anumită clasă cu o interfață adecvată. Cu toate acestea, nu puteți utiliza această clasă direct, deoarece citirile senzorului sunt luate în grade Fahrenheit. Ai nevoie de un adaptor care convertește temperatura în Celsius.

Implementarea

adaptor de spațiu de nume

static void Main()

// Creați adaptor și plasați o solicitare

Țintă țintă = adaptor nou ();

target.Request();

// Așteptați utilizatorul

public virtual void Solicitare()

Console.WriteLine("Called Target Request()");

Adaptor de clasă: țintă

private Adaptee adaptee = new Adaptee();

public override void Request()

// Posibil să faci o altă lucrare

// și apoi apelați SpecificRequest

adaptee.SpecificRequest();

public void SpecificRequest()

Console.WriteLine("Denumit SpecificRequest()");

Rezultatele aplicării modelului Adaptor

Avantajele modelului Adaptor

    Modelul Adaptor vă permite să reutilizați codul existent adaptând interfața sa incompatibilă într-o formă utilizabilă.

Dezavantajele modelului adaptorului

    Sarcina de conversie a interfețelor poate fi dificilă dacă apelurile clientului și/sau parametrii trecuți nu au o corespondență funcțională în obiectul care este adaptat.

    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

Adaptor de model, Wrapper

Numele și clasificarea modelului

Un adaptor este un model care structurează atât clasele, cât și obiectele.

Scopul modelului adaptorului

Adesea, un nou proiect software nu reușește să reutilizeze codul existent. De exemplu, clasele existente pot avea funcționalitatea dorită, dar au interfețe incompatibile. În astfel de cazuri, ar trebui să utilizați modelul Adaptor pentru a converti interfața unei clase în interfața alteia pe care o așteaptă clienții.

Modelul Adaptor, care este un pachet de software peste clasele existente, convertește interfețele acestora într-o formă potrivită pentru utilizarea ulterioară.

Să ne uităm la cel mai simplu exemplu de utilizare a modelului Adaptor Să dezvoltăm un sistem de climatizare. O componentă importantă a unui astfel de sistem este un senzor de temperatură, pentru care există deja un software gata făcut, care este o anumită clasă cu o interfață adecvată pentru lucrul cu scara Fahrenheit. Dar ne interesează temperatura pe scara Celsius. Problema poate fi rezolvată cu ușurință folosind un model Adaptor

Să luăm în considerare un alt exemplu - un editor grafic în care utilizatorii pot desena elemente grafice (linii, poligoane, text etc.) pe ecran și le pot organiza sub formă de imagini și diagrame. Abstracția principală a unui editor grafic este un obiect grafic, care are o formă schimbătoare și se înfățișează pe sine. Interfața obiectelor grafice este definită de clasa abstractă Shape. Editorul definește o subclasă a clasei Shape pentru fiecare tip de obiect grafic: LineShape pentru linii, PolygonShape pentru poligoane etc.

Clasele pentru forme geometrice de bază, cum ar fi LineShape și PolygonShape, sunt relativ ușor de implementat, deoarece capacitățile lor inerente de desen și editare sunt extrem de limitate. Dar subclasa Text Shape, care poate afișa și edita text, este mult mai complicată. În același timp, există biblioteci gata făcute pentru dezvoltarea interfețelor utilizator care oferă o clasă de vizualizare text dezvoltată pentru afișarea și editarea textului.

Ar fi posibil să se schimbe interfața clasei Text View pentru a se potrivi cu interfața Shape, dar acest lucru ar necesita codul sursă. Dar chiar dacă este disponibil, nu este deloc înțelept să schimbați vizualizarea textului - biblioteca nu ar trebui să se adapteze la interfețele fiecărei aplicații specifice.

În schimb, puteți defini clasa Text Shape astfel încât să o facă adapta Interfața Text View la interfața Shape. Acest lucru se poate face în două moduri: mostenind interfață de la Shape și implementare din Vizualizare text; prin includerea unei instanțe de vizualizare text într-o formă de text și prin implementarea formei de text în ceea ce privește interfața de vizualizare text. Aceste două abordări corespund unor variante ale modelului Adaptor în formele sale de clasă și obiect. Vom numi clasa Text Shape (Fig. 40) Adaptor.

Diagrama prezintă un adaptor de obiect. Puteți vedea cum cererea BoundingBox declarată în clasa Shape este tradusă într-o solicitare Get Extent definită în clasa Text View. Deoarece clasa Text Shape adaptează Text View la interfața Shape, editorul grafic poate folosi clasa TextView, chiar dacă are o interfață incompatibilă.

Adesea, adaptorul este responsabil pentru funcționalitatea pe care clasa de adaptare nu le poate oferi. În fig. 40 prezentat ca adaptor

returnează newTextManipulator^^

Orez. 40. Diagrama UML a adaptorului de obiecte

îndeplinește astfel de funcții. Utilizatorul ar trebui să poată muta orice obiect Shape într-o altă locație, dar clasa TextView nu oferă o astfel de operație. Text Shape poate adăuga funcționalitatea lipsă prin implementarea operației CreateManipulator a clasei Shape în sine, care returnează o instanță a subclasei Manipulator corespunzătoare.

Un manipulator este o clasă abstractă de obiecte care știe cum să anime o formă ca răspuns la acțiunile utilizatorului, cum ar fi tragerea formei în altă locație. Clasa Manipulator are subclase pentru diferite forme. De exemplu, TextManipulator este o subclasă de Text Shape. Prin returnarea unei instanțe a TextManipulator, obiectul clasei TextShape adaugă o nouă funcționalitate pe care clasa TextView nu o are, dar o necesită clasa Shape.

Aplicabilitate

Utilizați modelul Adaptor atunci când:

  • vrei să folosești o clasă existentă, dar interfața acesteia nu corespunde nevoilor tale;
  • veți crea o clasă reutilizabilă care trebuie să interacționeze cu clase anterior necunoscute sau neînrudite care au interfețe incompatibile;
  • (numai pentru adaptorul de obiecte!) trebuie să folosiți mai multe subclase existente, dar nu este practic să vă adaptați interfețele prin generarea de noi subclase din fiecare. În acest caz, adaptorul de obiecte poate adapta interfața clasei părinte comune.

Descrierea modelului de adaptor

Un adaptor de clasă folosește moștenirea multiplă pentru a adapta o interfață la alta.

Lăsați clasa a cărei interfață trebuie adaptată la forma dorită să aibă numele Adapt?e. Pentru a rezolva problema transformării interfeței, modelul Adaptor introduce următoarea ierarhie de clase:

  • clasa de bază virtuală Ţintă. Aici este declarată o interfață de utilizator de tipul adecvat. Numai această interfață este disponibilă utilizatorului;
  • clasa derivata Adaptor, care implementează interfața Target. Această clasă conține, de asemenea, un pointer sau referință la o instanță Adapt?e. Model Adaptor folosește acest indicator pentru a redirecționa apelurile clientului către Adapt?e. Din moment ce interfeţele Adapt?eȘi Ţintă sunt incompatibile între ele, aceste apeluri necesită de obicei conversie.

Structura

Structura modelului de adaptor este prezentată în Fig. 41.

Un adaptor de obiect impune compoziția obiectului.


adaptat->specificRequest()

Orez. 41. Diagrama de clasă UML a modelului Adaptor

Participanții

Target (Shape) - target: definește interfața specifică domeniului pe care o folosește Clientul.

Client (DrawingEditor) - client: intră în relații cu obiecte care satisfac interfața Target.

Adapt?e (Textview) - Adaptabil: definește o interfață existentă care trebuie adaptată.

Adaptor (Text Shape) - Adaptor: adaptează interfața Adapt?e la interfața țintă.

Relaţie

Clienții invocă operațiuni pe o instanță de adaptor. La rândul său, adaptorul apelează operațiile obiectului adaptabil sau ale clasei Adapt?e, care execută cererea.

rezultate

Rezultatele utilizării adaptoarelor de obiecte și de clasă variază.

Adaptor de clasă:

  • adaptează Adapt?e la țintă, delegând acțiunile unei anumite clase de Adapt?e. Prin urmare, acest model nu va funcționa dacă dorim să adaptăm o clasă și subclasele ei în același timp;
  • permite Adaptorului să suprascrie unele dintre operațiunile clasei adaptabile Adapt?e, deoarece Adapter nu este altceva decât o subclasă a Adapt?e;
  • introduce un singur obiect nou. Pentru a ajunge la clasa adaptabilă, nu este nevoie de acces suplimentar la pointer.

Adaptor obiect:

  • permite unui adaptor să lucreze cu multe obiecte adaptabile, adică adaptorul însuși și subclasele sale (dacă există). Adaptorul poate adăuga o nouă funcționalitate tuturor obiectelor adaptabile simultan;
  • face dificilă înlocuirea operațiunilor din clasa Adapt?e. Acest lucru ar necesita subclasarea Adapt?e și face ca Adapter să se refere la acea subclasă, mai degrabă decât Adapt?e în sine.

Adaptoarele variază foarte mult în ceea ce privește cantitatea de muncă necesară pentru a adapta interfața Adapt?e la interfața țintă. Acest lucru poate fi la fel de simplu ca o transformare, cum ar fi schimbarea numelor operațiunilor sau sprijinirea unui set complet diferit de operații. Cantitatea de muncă depinde de cât de diferite sunt interfețele claselor țintă și adaptabile între ele.

La primul pas de implementare, este necesar să se găsească o interfață „îngustă” pentru Adapt?e, adică cel mai mic subset de operațiuni care permite adaptarea. O interfață „îngustă” constând din doar câteva iterații este mai ușor de adaptat decât o interfață constând din câteva zeci de operațiuni.

O interfață „îngustă” poate fi implementată în diferite moduri.

  • 1. Folosind operații abstracte. Subclasele trebuie să implementeze aceste operații abstracte și să adapteze obiectul structurat ierarhic.
  • 2. Utilizarea obiectelor proxy. Cu această abordare, cererile de acces la structura ierarhică sunt transmise obiectului de autoritate.

Implementarea clasică a modelului Adaptor

Iată o implementare a modelului Adaptor. Pentru exemplul de mai sus, adaptăm citirile senzorului de temperatură al sistemului de climatizare, transformându-le din grade Fahrenheit în grade Celsius (se presupune că codul pentru acest senzor nu este disponibil pentru modificare).

// Clasa de senzori de temperatură ambientală deja existentă

Clasa FahrenheitSensor

// Obține citiri de temperatură în Fahrenheit float getFahrenheitTemp() ( float t = 32,0;

//... un cod returnează t;

~Senzor virtual()()

clasă Adaptor: Senzor public

Adaptor(FahrenheitSensor* p): p_fsensor(p) (

Adaptat) ( șterge p_fsensor;

float getTemperature() ( return (p_fsensor->getFahrenheitTemp()-32.0)*5.0/9.0;

FahrenheitSensor* p_fsensor;

Senzor* p = Adaptor nou (sensor Fahrenheit nou);

cout getTemperature()

Implementarea modelului Adaptor bazat pe moștenirea închisă

Lăsați senzorul de temperatură al sistemului nostru de climatizare să accepte funcția de reglare pentru citiri mai precise. Această funcție nu este necesară pentru a fi utilizată, motiv pentru care metoda corespunzătoare adjust() este declarată protejată de dezvoltatori în clasa FahrenheitSensor existentă.

Sistemul pe care îl dezvoltăm trebuie să suporte personalizarea măsurătorilor. Deoarece accesul la o metodă protejată printr-un pointer sau link este interzis, implementarea clasică a modelului Adaptor nu mai este potrivită aici. Singura soluție este să moștenești din clasa FahrenheitSensor. Interfața acestei clase trebuie să rămână inaccesibilă utilizatorului, deci moștenirea trebuie să fie privată.

Scopurile urmărite atunci când se utilizează moștenirea deschisă și cea închisă sunt diferite. În timp ce moștenirea deschisă este utilizată pentru moștenirea interfeței și implementării, moștenirea închisă este folosită numai pentru moștenirea implementării.

Clasa FahrenheitSensor

float getFahrenheitTempO ( float t = 32,0;

void adjustQ() // Reglați senzorul (metoda protejată)

~Senzor virtual()()

virtual float getTemperature() = 0;

virtual void adjust() = 0;

Clasa Adaptor: Senzor public, Senzor Fahrenheit privat

Adaptor() () float getTemperature() ( return (getFahrenheitTemp()-32.0)*5.0/9.0;

FahrenheitSensor::adjust();

Senzor * p = adaptor nou(); p->ajustare();

cout getTemperature()

Rezultatele aplicării modelului Adaptor

Avantajele modelului Adaptor

Modelul Adaptor vă permite să reutilizați codul existent adaptând interfața sa incompatibilă într-o formă utilizabilă.

Dezavantajele modelului adaptorului

Sarcina de conversie a interfețelor poate fi dificilă dacă apelurile clientului și/sau parametrii trecuți nu au o corespondență funcțională în obiectul care este adaptat.

Modele înrudite

Structura modelului Bridge este similară cu structura adaptorului, dar Bridge-ul are un scop diferit. Separă interfața de implementare, astfel încât ambele să poată fi modificate independent. Adaptorul este conceput pentru a schimba interfața existent obiect.

Modelul Decorator extinde funcționalitatea unui obiect prin schimbarea interfeței acestuia. Astfel, un Decorator este mai transparent pentru aplicație decât un Adaptor. În consecință, Decoratorul acceptă compoziția recursivă, ceea ce nu este posibil pentru adaptoarele „pure”.

Un proxy definește un reprezentant sau un substitut al altui obiect, dar nu îi schimbă interfața.