Am analizat deja utilizarea unui obiect singleton, dar este posibil să nu realizați încă că această strategie este un model de design și unul dintre cele mai utilizate în acest sens.
De fapt, există o mulțime de aceste modele și pot fi clasificate în funcție de scopul lor specific.
Clasificarea modelelor
Tipul de model | Aplicație |
---|---|
Creativ | Un tip care rezolvă problema creării obiectelor |
Structural | Modele care ne permit să construim o ierarhie de clasă corectă și extensibilă în arhitectura noastră |
Comportamental | Acest grup de modele facilitează interacțiunea sigură și convenabilă între obiectele dintr-un program. |
De obicei, un model este caracterizat de problema pe care o rezolvă. Să aruncăm o privire la câteva modele pe care le întâlnim cel mai des atunci când lucrăm cu Java:
Model | Scop |
---|---|
Singleton | Suntem deja familiarizați cu acest model - îl folosim pentru a crea și accesa o clasă care nu poate avea mai mult de o instanță. |
Iterator | De asemenea, suntem familiarizați cu acesta. Știm că acest model ne permite să iterăm peste un obiect de colecție fără a dezvălui reprezentarea sa internă. Se folosește cu colecții. |
Adaptor | Acest model conectează obiecte incompatibile, astfel încât acestea să poată lucra împreună. Cred că numele modelului adaptorului vă ajută să vă imaginați exact ce face acesta. Iată un exemplu simplu din viața reală: un adaptor USB pentru o priză de perete. |
Metoda șablonului |
Un model de programare comportamentală care rezolvă problema integrării și vă permite să schimbați pașii algoritmici fără a modifica structura unui algoritm. Imaginați-vă că avem un algoritm de asamblare a mașinii sub forma unei secvențe de pași de asamblare: Șasiu -> Caroseria -> Motor -> Interior cabină Dacă punem un cadru ranforsat, un motor mai puternic sau un interior cu iluminare suplimentară, nu trebuie să schimbăm algoritmul, iar secvența abstractă rămâne aceeași. |
Decorator | Acest model creează ambalaje pentru obiecte pentru a le oferi funcționalitate utilă. O vom considera ca parte a acestui articol. |
În Java.io, următoarele clase implementează modele:
Model | Unde este folosit în java.io |
---|---|
Adaptor |
|
Metoda șablonului | |
Decorator |
Model de decorator
Să ne imaginăm că descriem un model pentru amenajarea unei case.
În general, abordarea arată astfel:
Inițial, avem de ales dintre mai multe tipuri de case. Configurația minimă este un etaj cu acoperiș. Apoi folosim tot felul de decoratori pentru a schimba parametri suplimentari, ceea ce afectează în mod natural prețul casei.
Creăm o clasă abstractă House:
public abstract class House {
String info;
public String getInfo() {
return info;
}
public abstract int getPrice();
}
Aici avem 2 metode:
- getInfo() returnează informații despre numele și caracteristicile casei noastre;
- getPrice() returnează prețul configurației actuale a casei.
Avem, de asemenea, implementări standard pentru casă - cărămidă și lemn:
public class BrickHouse extends House {
public BrickHouse() {
info = "Brick House";
}
@Override
public int getPrice() {
return 20_000;
}
}
public class WoodenHouse extends House {
public WoodenHouse() {
info = "Wooden House";
}
@Override
public int getPrice() {
return 25_000;
}
}
Ambele clase moștenesc clasa House și înlocuiesc metoda prețului acesteia, stabilind un preț personalizat pentru o casă standard. Setăm numele în constructor.
În continuare, trebuie să scriem cursuri de decoratori. Aceste clase vor moșteni și clasa House . Pentru a face acest lucru, creăm o clasă de decorator abstract.
Acolo vom pune o logică suplimentară pentru schimbarea unui obiect. Inițial, nu va exista o logică suplimentară și clasa abstractă va fi goală.
abstract class HouseDecorator extends House {
}
În continuare, creăm implementări de decorator. Vom crea mai multe clase care ne permit să adăugăm caracteristici suplimentare casei:
public class SecondFloor extends HouseDecorator {
House house;
public SecondFloor(House house) {
this.house = house;
}
@Override
public int getPrice() {
return house.getPrice() + 20_000;
}
@Override
public String getInfo() {
return house.getInfo() + " + second floor";
}
}
Un decorator care adaugă un al doilea etaj casei noastre |
Constructorul decorator acceptă o casă pe care o vom „decor”, adică adăugăm modificări. Și suprascriem metodele getPrice() și getInfo() , returnând informații despre noua casă actualizată bazată pe cea veche.
public class Garage extends HouseDecorator {
House house;
public Garage(House house) {
this.house = house;
}
@Override
public int getPrice() {
return house.getPrice() + 5_000;
}
@Override
public String getInfo() {
return house.getInfo() + " + garage";
}
}
Un decorator care adaugă un garaj casei noastre |
Acum ne putem actualiza casa cu decoratori. Pentru a face acest lucru, trebuie să creăm o casă:
House brickHouse = new BrickHouse();
În continuare, ne-am setatcasavariabilă egală cu un nou decorator, care trece în casa noastră:
brickHouse = new SecondFloor(brickHouse);
Al nostrucasavariabila este acum o casa cu un al doilea etaj.
Să ne uităm la cazurile de utilizare care implică decoratori:
Exemplu de cod | Ieșire |
---|---|
|
Casa de caramida 20000 |
|
Casa din caramida + etaj al doilea 40000 |
|
Casa din caramida + etaj al doilea + garaj 45000 |
|
Casa din lemn + garaj + etaj 50000 |
|
Casa de lemn 25000 Casa din lemn + garaj 30000 |
Acest exemplu ilustrează beneficiul actualizării unui obiect cu un decorator. Deci nu am schimbatcasa de lemnobiectul în sine, dar în schimb a creat un nou obiect bazat pe cel vechi. Aici putem observa că avantajele vin cu dezavantaje: creăm de fiecare dată un nou obiect în memorie, crescând consumul de memorie.
Priviți această diagramă UML a programului nostru:
Un decorator are o implementare super simplă și schimbă dinamic obiectele, actualizându-le. Decoratorii pot fi recunoscuți de constructorii lor, care iau ca parametri obiecte de același tip abstract sau interfață ca și clasa curentă. În Java, acest model este utilizat pe scară largă în clasele I/O.
De exemplu, așa cum am observat deja, toate subclasele java.io.InputStream , OutputStream , Reader și Writer au un constructor care acceptă obiecte din aceleași clase.
GO TO FULL VERSION