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