composite. design pattern space purpose scopecreationalstructuralbehavioral classfactory...

34
COMPOSITE

Upload: kerry-rodgers

Post on 19-Jan-2016

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

COMPOSITE

Page 2: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Design Pattern SpacePurpose

Scope Creational Structural Behavioral

Class Factory Method Adapter InterpreterTemplate Method

Object Abstract factoryBuilderPrototypeSingleton

AdapterBridgeCompositeFacadeFlyweightProxy

Chain of ResponsibilityCommandIteratorMediatorMementoStateStrategyVisitor

Observer

Page 3: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Intent

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. This is called recursive composition.

Page 4: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Structure

Page 5: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Participants

Component declares the interface for object composition implements default behaviour declares an interface for accessing and managing the child

components Leaf

represents leaf objects in the composition Composite

defines behaviour for components having children stores child components implements child-related operations in the Component

interface Client

manipulates objects in the composition through the Composite interface

Page 6: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Consequences

Benefits It makes it easy to add new kinds of

components It makes clients simpler, since they do not

have to know if they are dealing with a leaf or a composite component

Page 7: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Example

import java.util.*;

interface Component {

public String defaultMethod();

public ArrayList<Component> getChildren();

public boolean addComponent(Component c);

public boolean removeComponent(Component c);

}

Page 8: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

class Composite implements Component { private String id; private ArrayList<Component> components = new

ArrayList<Component>(); public Composite(String identification) { id = identification; } public String defaultMethod() { String s = "(" + id + ":"; for (Component child : getChildren()) s = s + " " + child.defaultMethod(); return s + ")"; } public ArrayList<Component> getChildren() { return components; } public boolean addComponent(Component c) { return

components.add(c); } public boolean removeComponent(Component c) { return components.remove(c); }}

Page 9: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

class Leaf implements Component {

private String id;

public Leaf(String identification) { id = identification; }

public String defaultMethod() { return id; }

public ArrayList<Component> getChildren() { return null; }

public boolean addComponent(Component c) { return false; }

public boolean removeComponent(Component c) { return false; }

}

Page 10: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

class CompositePattern { public static void main(String[] args) { Composite england = new Composite("England"); Leaf york = new Leaf("York"); Leaf london = new Leaf("London"); england.addComponent(york); england.addComponent(london); england.removeComponent(york); Composite france = new Composite("France"); france.addComponent(new Leaf("Paris")); Composite europe = new Composite("Europe");

europe.addComponent(england); europe.addComponent(france); System.out.println( europe.defaultMethod() ); } }

Page 11: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Composite Example - Motivation GUI Windows and GUI elements

How does the window hold and deal with the different items it has to manage?

Widgets are different than WidgetContainers

Page 12: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Bad News Implementation

class Window { Buttons[] myButtons; Menus[] myMenus; TextAreas[] myTextAreas; WidgetContainer[] myContainers; public void update() { if ( myButtons != null ) for ( int k = 0; k < myButtons.length(); k++ ) myButtons[k].refresh(); if ( myMenus != null ) for ( int k = 0; k < myMenus.length(); k++ ) myMenus[k].display(); if ( myTextAreas != null ) for ( int k = 0; k < myButtons.length(); k++ ) myTextAreas[k].refresh();

Page 13: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Bad News Implementation

if ( myContainers != null )

for ( int k = 0; k < myContainers.length(); k++ )

myContainers[k].updateElements();

etc.

}

public void fooOperation() {

if ( blah )

etc.

if ( blah )

etc.

}

}

Page 14: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

The Composite Pattern

• Component implements default behavior for widgets when possible

• Button, Menu, etc overrides Component methods when needed

• WidgetContainer will have to overrides all widgetOperations

Page 15: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Implementation Issues

A composite object knows its contained components, that is, its children. Should components maintain a reference to their parent component? Depends on application, but having these

references supports the Chain of Responsibility pattern

Page 16: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Explicit Parent References

Aid in traversing the structureclass WidgetContainer {

Component[] myComponents;

public void update() {

if ( myComponents != null )

for ( int k = 0; k < myComponents.length(); k++ )

myComponents[k].update();

}

public add( Component aComponent ) {

myComponents.append( aComponent );

aComponent.setParent( this );

}

}

Page 17: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Explicit Parent References

class Button extends Component {

private Component parent;

public void setParent( Component myParent) {

parent = myParent;

}

etc.

}

Page 18: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Implementation Issues

Where should the child management methods (add(), remove(), getChild()) be declared? In the Component class: Gives transparency, since

all components can be treated the same. But it's not safe, since clients can try to do meaningless things to leaf components at run-time.

In the Composite class: Gives safety, since any attempt to perform a child operation on a leaf component will be caught at compile-time. But we lose transparency, since now leaf and composite components have different interfaces.

Page 19: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Transparent vs. Safe

Page 20: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Applicability

Use 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

Page 21: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Java Use of Composite - AWT Widgets

Page 22: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Another Example

Page 23: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Problem

Each of the company members receives a salary, and we could at any time ask for the cost of any employee to the company. We define the cost as the salary of that person

and those of all his subordinates.

Solution Here is an ideal example for a composite:

The cost of an individual employee is simply his salary (and benefits).

The cost of an employee who heads a department is his salary plus those of all his subordinates.

Page 24: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

We would like a single interface that will produce the salary totals correctly whether the employee has subordinates or not.

public float getSalaries();

At this point, we realize that the idea of all Composites having the same standard interface is probably naïve. We’d prefer that the public methods be related

to the kind of class we are actually developing. So rather than have generic methods like

getValue(), we’ll use getSalaries().

Page 25: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

The Employee Class

public class Employee { //Our Employee class will store the name and salary of each employee, and

String name; // allow us to fetch them as needed. float salary; Vector subordinates; //-------------------------------------- public Employee(String _name, float _salary) { name = _name; salary = _salary; subordinates = new Vector(); } //-------------------------------------- public float getSalary() { return salary; } //-------------------------------------- public String getName() { return name; }

Page 26: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

public void add(Employee e) { subordinates.addElement(e); } //-------------------------------------- public void remove(Employee e) { subordinates.removeElement(e); } public Enumeration elements() { return subordinates.elements(); }

Page 27: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

public float getSalaries() {

float sum = salary; //this one’s salary

//add in subordinates salaries

for(int i = 0; i < subordinates.size(); i++) {

sum +=

((Employee)subordinates.elementAt(i)).getSalaries();

return sum;

}

Page 28: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Building the Employee Tree

boss = new Employee("CEO", 200000);boss.add(marketVP = new Employee("Marketing VP",

100000));boss.add(prodVP = new Employee("Production VP", 100000));marketVP.add(salesMgr = new Employee("Sales Mgr",

50000));marketVP.add(advMgr = new Employee("Advt Mgr", 50000));//add salesmen reporting to Sales Managerfor (int i=0; i<5; i++) salesMgr .add(new Employee("Sales "+ new

Integer(i).toString(), 30000.0F +(float)(Math.random()-0.5)*10000));

advMgr.add(new Employee("Secy", 20000));

Page 29: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Building the Employee Tree

prodVP.add(prodMgr = new Employee("Prod Mgr", 40000));prodVP.add(shipMgr = new Employee("Ship Mgr", 35000));//add manufacturing stafffor (int i = 0; i < 4; i++) prodMgr.add( new Employee("Manuf "+ new Integer(i).toString(),

25000.0F +(float)(Math.random()-

0.5)*5000));//add shipping clerksfor (int i = 0; i < 3; i++) shipMgr.add( new Employee("ShipClrk "+ new Integer(i).toString(),

20000.0F +(float)(Math.random()-

0.5)*5000));

Page 30: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Visual JTree

private void addNodes(DefaultMutableTreeNode pnode, Employee emp) {

DefaultMutableTreeNode node; Enumeration e = emp.elements(); while(e.hasMoreElements()) { Employee newEmp = (Employee)e.nextElement(); node = new DefaultMutableTreeNode(newEmp.getName()); pnode.add(node); addNodes(node, newEmp); }}

Page 31: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory
Page 32: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Cost (Sum of Salaries)

public void valueChanged(TreeSelectionEvent evt) { //called when employee is selected in tree llist TreePath path = evt.getPath(); String selectedTerm = path.getLastPathComponent().toString(); //find that employee in the composite Employee emp = boss.getChild(selectedTerm); //display sum of salaries of subordinates(if any) if(emp != null) cost.setText(new Float(emp.getSalaries()).toString());}

Page 33: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Restrictions on Employee Classes e.g. never should have subordinatespublic void setLeaf(boolean b) {

isLeaf = b; //if true, do not allow children

}

//--------------------------------------

public boolean add(Employee e) {

if (! isLeaf)

subordinates.addElement(e);

return isLeaf; //false if unsuccessful

}

Page 34: COMPOSITE. Design Pattern Space Purpose ScopeCreationalStructuralBehavioral ClassFactory MethodAdapterInterpreter Template Method ObjectAbstract factory

Parent Reference

It is perfectly possible for any composite element to remember its parent by including it as part of the constructor:

public Employee(Employee _parent, String _name, float _salary) { name = _name; //save name salary = _salary; //and salary parent = _parent; //and parent subordinates = new Vector(); isLeaf = false; //allow children} This simplifies searching for particular

members and moving up the tree when needed.