Composite Pattern Facilitates the composition of objects into tree structures that represent part-whole hierarchies. These hierarchies consist of both primitive and composite objects.
Considerations Clients interact with objects through a component class. The approach enables clients to ignore the specifics of which leaf or composite class they use. New components can easily be added to a design.
The Composite Pattern :: Definition & Applicability The Composite Design pattern allows a client object to treat both single components and collections of components identically. Composite patterns are often used to represent recursive data structures. The recursive nature of the Composite structure naturally gives way to recursive code to process that structure. Use the Composite pattern when: You want to represent part-whole hierarchies of objects. You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly. Reference http://www.javaworld.com/javaworld/jw-09-2002/jw-0913-designpatterns.html 3
:: Example In the UML class diagram below: The Composite Pattern The Client uses an interface of abstract class We have used a class Component, AComponent, for some abstract task or tasks, operation() in Fig below. At run-time, the Client holds a reference to a concrete component such as Leaf1 or Leaf2. When the operation task is requested by the Client, the specific concrete behavior with the particular concrete component will be performed. 4
:: Consequences of the Composite Pattern The Composite Pattern The Composite pattern allows you to define a class hierarchy of simple objects and more complex composite objects so that they appear to be the same to the client program. Naturally applicable to recursive definitions (e.g., a tree). We will use the term a leaf to denote a tree with no substructure (e.g., Leaf1 or Leaf2 in previous slide) and a node to denote the others (Composite in previous slide). Because of this simplicity, the client can be simpler, since nodes and leaves are handled in the same way. The Composite pattern also makes it easy for you to add new kinds of components to your collection, as long as they support a similar programming interface. The composite is essentially a singly-linked tree, in which any of the objects may themselves be additional composites. 5
An example from Computer Graphics A picture here consists of lines, rectangles, text or a collection of simpler pictures. In the above diagram we have only included Draw method. It could include other operations on graphic objects such as resize or move. The Picture class represents a number of graphics objects. It can call Draw on its children and also uses children to compose pictures using primitive objects.
Observations The Component (Graphic) is an abstract class that declares the interface for the objects in the pattern. As the interface, it declares methods (such as Draw) that are specific to the graphical objects. Line, Rectangle, and Text are the so-called Leafs, which are subclasses that implement Draw to draw lines, rectangles, and text, respectively.
A concrete example We wish to represent the employee hierarchy of a typical company. There are two types of employees Employee and Manager. An object of the Manager class manages other employees and/or managers. These correspond to the composites. An object of class Employee corresponds to the leaf nodes. The user or the client class should not care whether it is dealing with an object of the Employee class or an object of the Manager class. In this example, the application is invoking the method getdescription() on any type of employee Manager or employee. If the object is of class Employee, the method returns the description of the employee - his/her name and salary. Otherwise, it returns the description of the manager - his/her name, how many persons he/she is supervising and the description of all people (manager or employee) that he/she is supervising.
public abstract class UserInterface { public abstract String getname(); public String getdescription(){ return getdescription(0); protected abstract String getdescription(int numberofblanksatfront); protected String generateblanksatfront(int numberofblanksatfront){ String result = ""; for (int i = 0; i < numberofblanksatfront; i++){ result += ' '; return result;
public class Employee extends UserInterface{ String employeename; double employeesalary; Employee(String employeename, double salary){ this.employeename = employeename; employeesalary = salary; public String getname() { return employeename; public String getdescription(int numberofblanksatfront) { return "\n" + generateblanksatfront(numberofblanksatfront) + getname() + " earns $" + employeesalary ;
public class Manager extends UserInterface{ String managername; ArrayList<UserInterface> employeelist; String department; Manager(String name, String dept ) { managername = name; department = dept; employeelist = new ArrayList<UserInterface>(); public void addsubordinate(userinterface subordinate){ employeelist.add(subordinate);
public UserInterface getsubordinate(int subordinatenumber){ return employeelist.get(subordinatenumber); public String getname() { return managername; public String getdescription(int numberofblanksatfront) { String result; result = "\n" + generateblanksatfront(numberofblanksatfront) + getname() + " supervises following " + employeelist.size() + " employees:"; for (UserInterface asubordinate:employeelist){ return result; result += asubordinate.getdescription(numberofblanksatfront + 4);
public class Test { public static void main(string[] args) { Employee e1, e2, e3, e4; Manager m1, m2, m3; e3 = new Employee("Tom", 70000.00); e4 = new Employee("Bob", 60000.00); e1 = new Employee("John", 35000.00); e2 = new Employee("Amit", 80000.00); m1 = new Manager("Mary", "Accounting"); m1.addsubordinate(e1); m1.addsubordinate(e2); m2 = new Manager("Paul", "Production"); m2.addsubordinate(e3); m2.addsubordinate(m1); m3 = new Manager("Liz", "Head Office"); m3.addsubordinate(e4); m3.addsubordinate(m1); m3.addsubordinate(m2); System.out.println(m3.getDescription());
Output produced Liz supervises following 3 employees: Bob earns $60000.0 Mary supervises following 2 employees: John earns $35000.0 Amit earns $80000.0 Paul supervises following 2 employees: Tom earns $70000.0 Mary supervises following 2 employees: John earns $35000.0 Amit earns $80000.0
Review Composite Pattern Participants Component (Or how the client programs view it) -- declares the interface for objects in the composition -- implements default behavior for the interface common to all classes, as appropriate -- declares an interface for accessing and managing its child components. Leaf -- defines behavior for primitive objects in the composition. Composite -- defines behavior for components having children. -- stores child components -- implements child-related operations in the Component interface.
Composite Pattern Collaborations Clients use the Component class interface to interact with objects in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards request to its child components, possibly performing additional operations before and/or after forwarding. Consequences Defines class hierarchies consisting of primitive objects and composite objects. Wherever client code expects a primitive object, it can also take a composite object. Makes the client simple. Clients can treat composite structures and individual objects uniformly. Makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Can make your design overly general. It makes it harder to restrict the components of a composite.