Kompozicija (projektni uzorak)
Kompozicija ili Sastav (engl. Composite) je objektno-orijentisani projektni uzorak. Pripada kategoriji objektnih uzoraka strukture.[1] Komponuje objekte u strukturu stabla (hijerarhija celina-deo) i omogućava klijentima da uniformno tretiraju individualne objekte i njihove kompozicije.[1] To se postiže time što se jasno definišu delovi, dok se celine (sastavi) predastavljaju kao delovi, ali imaju ulogu kontejnera tih delova.[2]
Česte upotrebe[uredi | uredi izvor]
Sastav ima veliku primenu kada je potrebno predstavljati hijerarhije celina-deo, što se postiže formiranjem strukture u obliku stabla.[1][2][3] Posebno je koristan kada je potrebno da korisnici ignorišu razlike između celina i delova, odnosno da ih tretiraju uniformno,[1] čime se korisničke klase podjednostavljuju i olakšavaju izmene, testiranja i nadogradnje.[2]
Učesnici[uredi | uredi izvor]
Postoje četiri učesnika za ovaj projektni uzorak.[1][2][3]
Komponenta[uredi | uredi izvor]
Deklariše zajedničko ponašanje za sve čvorove objektnog stabla. To znači da deklariše zajednički interfejs, ali moguće je deklarisati ili implementirati i pristup deci, kao i roditeljima, ako ih komponenta ima.[1]
List[uredi | uredi izvor]
Implementira ponašanje komponente i predstavlja primitivan objekat u kompoziciji.[1] On je zapravo list objektnog stabla što znači da nema decu.[1]
Sastav (Kompozicija)[uredi | uredi izvor]
Predstavlja objekat koji implementira onaj deo interfejsa za komponente, koji je vezan za decu, jer se ne radi o listu.[1] Sadrži decu komponente, što znači da je moguće i da jedan sastav bude dete drugog sastava.[1]
Korisnik[uredi | uredi izvor]
Preko interfejsa komponente, manipuliše objektima stabla.[1]
Dijagram klasa[uredi | uredi izvor]
Dijagram klasa i primer objektnog stabla za projektni uzorak kompozicija se nalazi na slici desno. Prikazan je preko Objedinjenog jezika za modeliranje.
Prednosti i mane[uredi | uredi izvor]
Kao što je već rečeno, korišćenje ovog projektnog uzorka podjednostavljuje klase korisnika, i omogućava lako dodavanje novih komponenata što uključuje i nove sastave, ne samo čvorove.[1][2] Zbog toga je moguća dinamična izgradnja i menjanje kompleksnih struktura u vreme prevođenja.[2] Ipak, mogući problem sa sastavom jeste upravo u komponenti - teže je onemogućiti dodavanje određenih komponenata stablu, koje ne želimo da vidimo u njemu.[1] Takođe, jedan od mogućih problema delimično vezan za prethodni jeste vezan za pojavu u implementaciji da se može doći do oblika Component.addComponent() kada je Component zapravo list, što predstavlja grešku, jer ne želimo listu da dodajemo decu.[3]
Implementacija[uredi | uredi izvor]
Prilikom implementacije ovog projektnog uzorka, treba voditi računa mnogim stvarima, pogotovu onih koji se tiču stabla kao takvog. Treba implementirati operacije vezane za decu ili, opciono i roditelje, ali voditi računa prilikom slučajeva kada se određene komponente mogu deliti između drugih komponenata. Takođe, treba težiti ka maksimalnom interfejsu za komponentu - poželjno je da klijent bude rasterećen toga da li koristi sastav ili list. Zbog toga treba što više operacija deklarisati u interfejsu za komponentu. Prilikom odabira strukture za komponente da bi skladištile decu, moguće je koristiti veoma raznovrsne strukture - od ulančanih listi, preko stabala, nizova i heš tabela.[1]
Ispod je dat primer implementacije graditelja na programskom jeziku Java, preuzet sa sajta koji se može naći na spoljašnjim linkovima.[2] Klase su, naravno, posebni fajlovi i potrebno je uključiti odgovarajuće pakete, ali su ovde prikazani na jednom mestu.
//Klasa koja predstavlja Komponentu objektnog stabla
public abstract class Component {
private String name;
public Component(String name) {
this.name = name;
}
public abstract String operation();
public String getName() {
return name;
}
//Default implementacija za operacije koje barataju decom
public boolean add(Component child) { //Po default-u, vraca false
return false;
}
public Iterator<Component> iterator() { // null iterator
return Collections.<Component>emptyIterator();
}
}
//Klasa koja predstavlja List
public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
public String operation() {
return getName();
}
}
//Klasa koja predstavlja Kompoziciju
public class Composite extends Component {
private List<Component> children = new ArrayList<Component>();
public Composite(String name) {
super(name);
}
public String operation() {
Iterator<Component> it = children.iterator();
String str = getName();
Component child;
while (it.hasNext()) {
child = it.next();
str += child.operation();
}
return str;
}
//Treba "pregaziti" (override) default operacije
@Override
public boolean add(Component child) {
return children.add(child);
}
@Override
public Iterator<Component> iterator() {
return children.iterator();
}
}
Literatura[uredi | uredi izvor]
- Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. str. 163-173.
- Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. str. 163-173.
Reference[uredi | uredi izvor]
- ^ a b v g d đ e ž z i j k l lj Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. str. 163-173.
- ^ a b v g d đ e ž „Composite”. w3sDesign. Pristupljeno 04. 01. 2019.
- ^ a b v „Composite”. JavaWorld from IDG. Arhivirano iz originala 05. 01. 2019. g. Pristupljeno 04. 01. 2019.