160 likes | 366 Views
The Composite Design Pattern. aComposite. Example : complex graphic application, with hierarchically nested objects. Main idea : Containers and leaf objects appear the same to clients. Up and down delegation : A container may delegate to all contained objects.
E N D
The Composite Design Pattern aComposite • Example: complex graphic application, with hierarchically nested objects. • Main idea: Containers and leaf objects appear the same to clients. • Up and down delegation: • A container may delegate to all contained objects. • A leaf/container may delegate to containing objects. aLeaf aComposite aLeaf aLeaf aLeaf aLeaf
Composite pattern - motivation Graphic Draw() Add(Graphic) Remove(Graphic) GetChild(int) graphics Picture Rectangle Text Line forall g in graphics Draw( ) Draw( ) Draw( ) Draw( ) g.Draw() Add(Graphic g) Remove(Graphic) GetChild(int) add g to list of graphics
Composite Class Diagram Graphic Draw() Add(Graphic) Remove(Graphic) GetChild(int) graphics Picture Rectangle Text Line forall g in graphics Draw( ) Draw( ) Draw( ) Draw( ) g.Draw() Add(Graphic g) Remove(Graphic) GetChild(int) add g to list of graphics
Composite object structure aComposite aLeaf aComposite aLeaf aLeaf aLeaf aLeaf
Composite: General Class Diagram • Component (Graphic) • declares interface for objects in the composition • implements default behavior • declares an interface for accessing and managing its child components • (optional) declares an interface for accessing a component’s parent • Leaf (Rectangle, Line, Text etc.) • defines behavior for primitive objects in the composition • Composite (Picture) • defines behavior for components having children • stores child components • implements child-related operations in the Component interface • Client • manipulates objects in the composition through the Component interface Component Operation() Add(Component) Remove(Component) GetChild(int) children Composite Client Operation() forall g in children Add(Component) g.Operation() Remove(Component) GetChild(int) Leaf Operation()
Participants • Component (Graphic) • declares interface for objects in the composition • implements default behavior • declares an interface for accessing and managing its child components • (optional) declares an interface for accessing a component’s parent • Leaf (Rectangle, Line, Text etc.) • defines behavior for primitive objects in the composition • Composite (Picture) • defines behavior for components having children • stores child components • implements child-related operations in the Component interface • Client • manipulates objects in the composition through the Component interface
Implementation • Explicit parent references • define the parent reference in the Component class • essential to maintain the invariant that all children of a composite have as their parent the composite that in turn has them as children • easiest way to ensure - change the component’s parent only when it’s being added or removed from composite • Sharing components • multiple parents • ambiguities as a request propagates up the structure
Implementation: Maximizing the Component interface • Goal: clients must be unaware of a specific Leaf or Composite classes they are using • To attain the goal:Component class should define as many common operations as possible • The goal sometimes conflict with the principle of class hierarchy design: “A class should only define operations that are meaningful for its subclasses” • Definition of the interface for accessing the children in Component seems inapplicable for leaves • But, • we can see a Leaf as a Component that never has children • a default operation for child access in the Component class that never returns any children
Implementation (3/4) • Declaring the child management operations • Trade-off between safety and transparency • Declare these operations in Component and make them meaningful for Leaf classes • all components are treated uniformly (transparency) • clients may try to do meaningless operations like add and remove object from leaves (costs safety) • Declare these operations in Composite • any attempt to add/remove children from leaves will be caught at compile time (safety) • transparency is lost • Should component implement a list of Components • space penalty for every leaf • better implement the list in Composite • Child ordering • Iterators!
Implementation (4/4) • Who will delete components? • Make a Composite responsible for deleting its children when it’s destroyed • Exception: when leaves are immutable and can be shared
Composite pattern - implementation • Explicit parent references • define the parent reference in the Component class • essential to maintain the invariant that all children of a composite have as their parent the composite that in turn has them as children • easiest way to ensure - change the component’s parent only when it’s being added or removed from composite • Sharing components • multiple parents • ambiguities as a request propagates up the structure
More Implementation Issues • Maximizing the Component interface • Goal: clients must be unaware of a specific Leaf or Composite classes they are using • To attain the goal:Component class should define as many common operations as possible • The goal sometimes conflict with the principle of class hierarchy design: “A class should only define operations that are meaningful for its subclasses” • Definition of the interface for accessing the children in Component seems inapplicable for leaves • But, • we can see a Leaf as a Component that never has children • a default operation for child access in the Component class that never returns any children
Issues • Declaring the child management operations • Trade-off between safety and transparency • Declare these operations in Component and make them meaningful for Leaf classes • all components are treated uniformly (transparency) • clients may try to do meaningless operations like add and remove object from leaves (costs safety) • Declare these operations in Composite • any attempt to add/remove children from leaves will be caught at compile time (safety) • transparency is lost • Should component implement a list of Components • space penalty for every leaf • better implement the list in Composite • Child ordering • Iterators! • Who will delete components? • Make a Composite responsible for deleting its children when it’s destroyed • Exception: when leaves are immutable and can be shared
Composite pattern - structure Component Operation() Client Add(Component) Remove(Component) forall g in children GetChild(int) g.Operation() children Composite Leaf Operation() Operation() Add(Component) Remove(Component) GetChild(int)