Thursday, March 3, 2011

Composite Pattern in Java

Composite allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Whenever we have a requirement of handling all the objects in the same structure we can go for composite pattern, where we can create a tree structure that contain both composition of objects and individual objects as nodes and treat all of them uniformly by using same operations.
A Composite contains components i.e.(composites(again can contain components) and leaf elements(cannot contain components again)).
Base Component defines an interface for all objects in the composition. The Client uses this base component class to deal with the objects in the composition. It may also provide the default behaviour for adding,removing or accessing child components. But mostly Component is an interface.
Composite: Defines beahviour of components having children and stores the child components. We can add and remove Component instances to this composite dynamically.
Leaf : Defines the behaviour for the elements in the composition. It doesn't have references to other Components
First we need to have a Component Interface.(BaseComponent where even you can give some default implementation also)

//Component
public interface Component {
public void add(Component countryComponent);
public void remove(Component countryComponent);
public Component getChild(int i);
public String getName();
public String getDescription();
public void print();
}



Then we have Leaf implementation, which further does'nt have references to other components.


//Leaf
public class Leaf implements Component{
private String name;
private String description;

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

/* these three methods doesn't make
* sense for Leaf. So we can even make
* the Base Component as abstract Class
* and provide the default implementation
* instead of this approach.
*/

public void add(Component state){
System.out.println("Sorry, leaf can't have components ");
}

public void remove(Component state){
System.out.println("Sorry, leaf can't have components ");
}

public Component getChild(int i){
System.out.println("Sorry, leaf can't have components ");
throw new UnsupportedOperationException();
}

public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}



and finally the Composite Implementation which again can contain child components.


// Composite
public class Composite implements Component{
private String name;
private String description;

// list of State Components
List<Component> components = new ArrayList<Component>();

public Composite(String name, String description){
this.name = name;
this.description = description;
}

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

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

public Component getChild(int i){
return components.get(i);
}
public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
Iterator<Component> iterator = components.iterator();
while(iterator.hasNext()){
Component component = iterator.next();
component.print();
}
}

public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}


}




public class Test {
public static void main(String[] args) {
Component leaf = new Leaf("leaf","No components futher");
Component composite = new Composite("composite","Again has components");
Component subcomposite = new Composite("subcomposite","Sub Composite again contain components");

Component baseComponent = new Composite("BaseComponent","Includes all other components");

baseComponent.add(leaf);
baseComponent.add(composite);
baseComponent.add(subcomposite);

baseComponent.print();
}
}


A general consideration when implementing this pattern is whether each component should have a reference to its
container (composite). The benefit of such a reference is that it eases the traversal of the tree, but it also decreases your flexibility.
There are many tradeoffs in implementing Composite. You need to balance transperency and safety with your needs.
Hope this explanation helps.
References : Applied Java Patterns by Stephen Stelting and Olav Maassen

No comments:

Post a Comment

Chitika