노현진's Blog

Composite Pattern

Composite Pattern에 대해 설명하는 페이지입니다.

Posted
Preview Image
By HyunJinNo

Tags

Design Pattern, Java

1. Introduction

  • Purpose
    • Facilitates the creation of object hierarchies where each object can be treated independently or as a set of nested objects through the same interface.
  • Use When
    • Hierarchical representations of objects are needed.
    • Objects and compositions of objects should be treated uniformly.

2. Characteristics

  • composes objects into tree structures to represent whole-part hierarchies.
  • lets clients treat individual objects and compositions of objects uniformly.
  • Child Mgt. Interface
    • Placing in Component class gives Transparency.
      • since all components can be treated the same. However, it is not safe. Clients can try to do meaningless things to leaf components at run-time.
    • Placing in Composite class gives Safety.
      • since any attempt to perform a child operation on a leaf component will be caught at compile-time. However, we lose transparency because now leaf and composite components have different interfaces.
  • Composite vs Decorator
    • Both have similar structure diagrams
      • recursive composition to organize an open-ended number of objects
    • Different intentions
      • Decorator lets you add responsibilities to objects without subclassing
      • Composite's focus is not on embellishment but on representation
      • They are complementary; hence, Composite and Decorator are often used in concert
  • Iterator
    • Provide a way to access the elements of an aggregate object (=typically uses composite pattern) sequentially without exposing its underlying representation

4. How to Use (Example)

  • Component

    java
    1public class Component {
    2    public void add(Component component) {
    3        throw new UnsupportedOperationException();
    4    }
    5}
  • Leaf

    java
    1public class Leaf extends Component {
    2    public String name;
    3    public Leaf(String name) {
    4        this.name = name;
    5    }
    6    public String getName() {
    7        return name;
    8    }
    9    public Iterator createIterator() {
    10        return new NullIterator();
    11    }
    12}
    java
    1public class NullIterator implements Iterator {
    2    public Object next() {
    3        return null;
    4    }
    5    public boolean hasNext() {
    6        return false;
    7    }
    8    public void remove() {
    9        throw new UnsupportedOperationException();
    10    }
    11}
  • Composite

    java
    1import java.util.ArrayList;
    2
    3public class Composite extends Component {
    4    public String name;
    5    public ArrayList<Component> components;
    6    public Iterator iterator = null;
    7
    8    public Composite(String name) {
    9        this.name = name;
    10        components = new ArrayList<Component>();
    11    }
    12
    13    @Override
    14    public void add(Component component) {
    15        components.add(component);
    16    }
    17
    18    public Iterator createIterator() {
    19        if (iterator == null) {
    20            iterator = new CompositeIterator(components.iterator());
    21        }
    22        return iterator;
    23    }
    24}
    java
    1import java.util.Stack;
    2
    3public class CompositeIterator implements Iterator {
    4    public Stack<Component> stack = new Stack<Component>();
    5    public CompositeIterator(Iterator iterator) {
    6        stack.push(iterator);
    7    }
    8    public Object next() {
    9        if (hasNext()) {
    10            Iterator iterator = (Iterator) stack.peek();
    11            Component component = (Component) iterator.next();
    12            if (component instanceof Composite) {
    13                stack.push(component.createIterator());
    14            }
    15            return component;
    16        } else {
    17            return null;
    18        }
    19    }
    20    public boolean hasNext() {
    21        if (stack.empty()) {
    22            return false;
    23        }
    24        Iterator iterator = (Iterator) stack.peek();
    25        if (!iterator.hasNext()) {
    26            stack.pop();
    27            return hasNext();
    28        } else {
    29            return true;
    30        }
    31    }
    32    public void remove() {
    33        throw new UnsupportedOperationException();
    34    }
    35}

© HyunJinNo. Some rights reserved.