Post

Composite Pattern

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

Composite Pattern

Tags
Design Pattern, Java

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.

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

How to Use (Example)

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

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