Композиција (пројектни узорак)
Композиција или Састав (енгл. Composite) је објектно-оријентисани пројектни узорак. Припада категорији објектних узорака структуре.[1] Компонује објекте у структуру стабла (хијерархија целина-део) и омогућава клијентима да униформно третирају индивидуалне објекте и њихове композиције.[1] То се постиже тиме што се јасно дефинишу делови, док се целине (састави) предастављају као делови, али имају улогу контејнера тих делова.[2]
Честе употребе
[уреди | уреди извор]Састав има велику примену када је потребно представљати хијерархије целина-део, што се постиже формирањем структуре у облику стабла.[1][2][3] Посебно је користан када је потребно да корисници игноришу разлике између целина и делова, односно да их третирају униформно,[1] чиме се корисничке класе подједностављују и олакшавају измене, тестирања и надоградње.[2]
Учесници
[уреди | уреди извор]Постоје четири учесника за овај пројектни узорак.[1][2][3]
Компонента
[уреди | уреди извор]Декларише заједничко понашање за све чворове објектног стабла. То значи да декларише заједнички интерфејс, али могуће је декларисати или имплементирати и приступ деци, као и родитељима, ако их компонента има.[1]
Лист
[уреди | уреди извор]Имплементира понашање компоненте и представља примитиван објекат у композицији.[1] Он је заправо лист објектног стабла што значи да нема децу.[1]
Састав (Композиција)
[уреди | уреди извор]Представља објекат који имплементира онај део интерфејса за компоненте, који је везан за децу, јер се не ради о листу.[1] Садржи децу компоненте, што значи да је могуће и да један састав буде дете другог састава.[1]
Корисник
[уреди | уреди извор]Преко интерфејса компоненте, манипулише објектима стабла.[1]
Дијаграм класа
[уреди | уреди извор]Дијаграм класа и пример објектног стабла за пројектни узорак композиција се налази на слици десно. Приказан је преко Обједињеног језика за моделирање.
Предности и мане
[уреди | уреди извор]Као што је већ речено, коришћење овог пројектног узорка подједностављује класе корисника, и омогућава лако додавање нових компонената што укључује и нове саставе, не само чворове.[1][2] Због тога је могућа динамична изградња и мењање комплексних структура у време превођења.[2] Ипак, могући проблем са саставом јесте управо у компоненти - теже је онемогућити додавање одређених компонената стаблу, које не желимо да видимо у њему.[1] Такође, један од могућих проблема делимично везан за претходни јесте везан за појаву у имплементацији да се може доћи до облика Component.addComponent() када је Component заправо лист, што представља грешку, јер не желимо листу да додајемо децу.[3]
Имплементација
[уреди | уреди извор]Приликом имплементације овог пројектног узорка, треба водити рачуна многим стварима, поготову оних који се тичу стабла као таквог. Треба имплементирати операције везане за децу или, опционо и родитеље, али водити рачуна приликом случајева када се одређене компоненте могу делити између других компонената. Такође, треба тежити ка максималном интерфејсу за компоненту - пожељно је да клијент буде растерећен тога да ли користи састав или лист. Због тога треба што више операција декларисати у интерфејсу за компоненту. Приликом одабира структуре за компоненте да би складиштиле децу, могуће је користити веома разноврсне структуре - од уланчаних листи, преко стабала, низова и хеш табела.[1]
Испод је дат пример имплементације градитеља на програмском језику Јава, преузет са сајта који се може наћи на спољашњим линковима.[2] Класе су, наравно, посебни фајлови и потребно је укључити одговарајуће пакете, али су овде приказани на једном месту.
//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();
}
}
Литература
[уреди | уреди извор]- Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. стр. 163-173.
- Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. стр. 163-173.
Референце
[уреди | уреди извор]- ^ а б в г д ђ е ж з и ј к л љ Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. стр. 163-173.
- ^ а б в г д ђ е ж „Composite”. w3sDesign. Приступљено 04. 01. 2019.
- ^ а б в „Composite”. JavaWorld from IDG. Архивирано из оригинала 05. 01. 2019. г. Приступљено 04. 01. 2019.