Композиција (пројектни узорак)

Композиција или Састав (енгл. Composite) је објектно-оријентисани пројектни узорак. Припада категорији објектних узорака структуре.[1] Компонује објекте у структуру стабла (хијерархија целина-део) и омогућава клијентима да униформно третирају индивидуалне објекте и њихове композиције.[1] То се постиже тиме што се јасно дефинишу делови, док се целине (састави) предастављају као делови, али имају улогу контејнера тих делова.[2]

Честе употребе

уреди

Састав има велику примену када је потребно представљати хијерархије целина-део, што се постиже формирањем структуре у облику стабла.[1][2][3] Посебно је користан када је потребно да корисници игноришу разлике између целина и делова, односно да их третирају униформно,[1] чиме се корисничке класе подједностављују и олакшавају измене, тестирања и надоградње.[2]

Учесници

уреди

Постоје четири учесника за овај пројектни узорак.[1][2][3]

Компонента

уреди

Декларише заједничко понашање за све чворове објектног стабла. То значи да декларише заједнички интерфејс, али могуће је декларисати или имплементирати и приступ деци, као и родитељима, ако их компонента има.[1]

Лист

уреди

Имплементира понашање компоненте и представља примитиван објекат у композицији.[1] Он је заправо лист објектног стабла што значи да нема децу.[1]

Састав (Композиција)

уреди

Представља објекат који имплементира онај део интерфејса за компоненте, који је везан за децу, јер се не ради о листу.[1] Садржи децу компоненте, што значи да је могуће и да један састав буде дете другог састава.[1]

Корисник

уреди

Преко интерфејса компоненте, манипулише објектима стабла.[1]

Дијаграм класа

уреди
 
Дијаграм класа пројектног узорка Композиција, као и пример објектног стабла које се може формирати.[2]

Дијаграм класа и пример објектног стабла за пројектни узорак композиција се налази на слици десно. Приказан је преко Обједињеног језика за моделирање.

Предности и мане

уреди

Као што је већ речено, коришћење овог пројектног узорка подједностављује класе корисника, и омогућава лако додавање нових компонената што укључује и нове саставе, не само чворове.[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();
      } 
}

Литература

уреди

Референце

уреди
  1. ^ а б в г д ђ е ж з и ј к л љ Johnson, Ralph; Gamma, Erich; Vlissides, John; Helm, Richard (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. стр. 163-173. 
  2. ^ а б в г д ђ е ж „Composite”. w3sDesign. Архивирано из оригинала 04. 01. 2019. г. Приступљено 04. 01. 2019. 
  3. ^ а б в „Composite”. JavaWorld from IDG. Архивирано из оригинала 05. 01. 2019. г. Приступљено 04. 01. 2019. 

Спољашње везе

уреди