Wednesday, May 6, 2015

Composite Pattern - structural design pattern

The composite pattern is a structural design pattern. In the composite pattern, a tree structure exists where identical operations can be performed on leaves and nodes. A node in a tree is a class that can have children. A node class is a 'composite' class. A leaf in a tree is a 'primitive' class that does not have children. The children of a composite can be leaves or other composites.
The leaf class and the composite class share a common 'component' interface that defines the common operations that can be performed on leaves and composites. When an operation on a composite is performed, this operation is performed on all children of the composite, whether they are leaves or composites. Thus, the composite pattern can be used to perform common operations on the objects that compose a tree.
The Gang of Four description of the composite pattern defines a client's interaction with the tree struture via a Component interface, where this interface includes the common operations on the composite and leaf classes, and the add/remove/get operations on the composites of the tree. This seems slightly awkward since a leaf does not implement the add/remove/get operations. In my opinion, in JavaSW it makes more sense to define the common leaf/composite operations on a Component interface, but to put the add/remove/get composite operations in a separate interface or to simply implement them in the composite class.
Now we'll look at an example of the composite pattern. First, we'll declare a Component interface that declares the operations that are common for the composite class and the leaf class. This allows us to perform operations on composites and leaves using one standard interface.

Component.java

package com.cakes;

public interface Component {

 public void sayHello();

 public void sayGoodbye();

}
The Leaf class has a name field and implements the sayHello() and sayGoodbye() methods of the Component interface by outputting messages to standard output.

Leaf.java

package com.cakes;

public class Leaf implements Component {

 String name;

 public Leaf(String name) {
  this.name = name;
 }

 @Override
 public void sayHello() {
  System.out.println(name + " leaf says hello");
 }

 @Override
 public void sayGoodbye() {
  System.out.println(name + " leaf says goodbye");
 }

}
The Composite class implements the Component interface. It implements the sayHello() and sayGoodbye() methods by calling these same methods on all of its children, which are Components (since they can be both Leaf objects and Composite objects, which both implement the Component interface).

Composite.java

package com.cakes;

import java.util.ArrayList;
import java.util.List;

public class Composite implements Component {

 List<Component> components = new ArrayList<Component>();

 @Override
 public void sayHello() {
  for (Component component : components) {
   component.sayHello();
  }
 }

 @Override
 public void sayGoodbye() {
  for (Component component : components) {
   component.sayGoodbye();
  }
 }

 public void add(Component component) {
  components.add(component);
 }

 public void remove(Component component) {
  components.remove(component);
 }

 public List<Component> getComponents() {
  return components;
 }

 public Component getComponent(int index) {
  return components.get(index);
 }

}
The CompositeDemo class demonstrates the composite pattern. It creates 5 Leaf objects. It adds two of these two a Composite object and two of these to another Composite object. It adds these two Composite objects and the last Leaf object to another Composite object. It calls sayHello() on leaf1, then sayHello() on composite1, then sayHello() on composite2, and then sayGoodbye() on composite3.

CompositeDemo.java

package com.cakes;

public class CompositeDemo {

 public static void main(String[] args) {

  Leaf leaf1 = new Leaf("Bob");
  Leaf leaf2 = new Leaf("Fred");
  Leaf leaf3 = new Leaf("Sue");
  Leaf leaf4 = new Leaf("Ellen");
  Leaf leaf5 = new Leaf("Joe");

  Composite composite1 = new Composite();
  composite1.add(leaf1);
  composite1.add(leaf2);

  Composite composite2 = new Composite();
  composite2.add(leaf3);
  composite2.add(leaf4);

  Composite composite3 = new Composite();
  composite3.add(composite1);
  composite3.add(composite2);
  composite3.add(leaf5);

  System.out.println("Calling 'sayHello' on leaf1");
  leaf1.sayHello();

  System.out.println("\nCalling 'sayHello' on composite1");
  composite1.sayHello();

  System.out.println("\nCalling 'sayHello' on composite2");
  composite2.sayHello();

  System.out.println("\nCalling 'sayGoodbye' on composite3");
  composite3.sayGoodbye();

 }

}
The console output of executing CompositeDemo is shown here.

Console Output

Calling 'sayHello' on leaf1
Bob leaf says hello

Calling 'sayHello' on composite1
Bob leaf says hello
Fred leaf says hello

Calling 'sayHello' on composite2
Sue leaf says hello
Ellen leaf says hello

Calling 'sayGoodbye' on composite3
Bob leaf says goodbye
Fred leaf says goodbye
Sue leaf says goodbye
Ellen leaf says goodbye
Joe leaf says goodbye
As seen in the output, the composite pattern allows us to perform operations on the composites and leaves that make up a tree structure via a common interface.


Source : http://www.avajava.com/tutorials/lessons/composite-pattern.html?page=1

No comments :

Post a Comment