com
http://www.openloop.com/softwareEngineering/patterns/designPattern/dPattern_wholePart.htm
Introduction
Sometimes called Composite
Helps with the aggregation of components (parts) that together form a semantic unit (whole).
Direct access to the Parts is not possible
Compose objects into tree structures to represent part-whole hierarchies.
Whole-Part lets clients treat individual objects and compositions of object uniformly
Supported in OO Programming Language
Whole-Part is part of why OOP design the way it is
Remember to read the text book
Example
Graphics applications, like drawing editors, let users build complex diagrams out of simple components.
For example, a graph might contain lines, rectangles, texts, pictures
The user can group components to form larger components, which in turn can be grouped to form still
larger components
A simple implementation could define classes for graphical primitives such as Text and Lines plus other
classes that act as containers for these primitives
Computer-Aided Design (CAD)
Java Beans
DevPack
GL, OpenGL ?
Context
Implementing aggregate objects
Problem
A complex object should either be decomposed into smaller objects or composed of existing objects, to
support reusability, changeability and the recombination of the constituent objects in other types of
aggregate
Clients should see the aggregate object as an atomic object that does not allow any direct access to its
constituent parts
Code that uses these classes must treat primitive (Text, Lines, etc.) and container (Graphic) objects
differently
Having to distinguish these objects makes the application more complex.
Solution
Use a component that encapsulates smaller objects, and prevents clients from accessing these
constituent parts directly
Use an interface as the only means of access to the functionality of the encapsulated objects (appear as a
semantic unit)
An assembly-parts relationship differentiates between a product and its parts or subassemblies
A container-contents relationship
A collection-members relationship helps to group similar objects - such as an organization and its members
Structure
Two types of participant
Two CRC cards
Class: Whole
Responsibility:
Aggregates several smaller objects
Provides services built on top of part objects
Acts as a wrapper around its constituent parts
Collaborators: Part
Class: Part
Responsibility:
Pepresents a particular object and its services
Collaborators: Whole object: An aggregation of smaller objects
Component
Leaf
Composite
Client
Implementation
Using Graphic as example
An abstract class that represents both primitives and their containers. Here, this class is Graphic
It declares operations, like Draw() here, that are specific to the object family
It also declares operations that all composite object share, such operations for accessing and managing its
children, like Add(Graphic) here
The subclasses define primitive objects, like Line, Rectangle, and Text here.
Each primitive object implements operations, for example, class Line implements Draw() to draw lines.
Primitive objects have no child objects, none of these subclasses implements child-related operations, for
example, class Line does not implement child-related operation Add(Graphic)
The Picture class defines an aggregate of Graphic objects
Picture implements Draw() to call Draw() on its children, and it implements child-related operations
accordingly
Because the Picture interface conforms to the Graphic interface, Picture objects can compose other
Pictures recursively.
In General
1. Design the public Interface of the Whole
2. Separate the Whole into Parts, or make it from existing ones (Use either bottom-up, top-down or both
mixed)
3. Use existing Parts from component libraries or class libraries or package, specify their collaboration if you
use bottom-up approach
4. Partition the Whole's services into smaller collaborating services and map these collaborating services to
separate Parts if you follow a top-down approach
5. Specific the services of the Whole in terms of services of the Parts
6. Implement the Parts (Recursively if Parts are not leaf)
7. Implement the Whole by putting all the Parts together
Cleaning Up
The Component class should define as many common operations for Composite
and Leaf classes as possible
Do we conflict the principle of class hierarchy design
Should we declare these operations in the Whole and make them meaningful for
Part/Leaf classes?
Should we declare and define them only in Composite and its subclasses?
What is the trade-off between safety and transparency?
Defining the child management interface at the root of the class hierarchy gives you transparency, because
you can treat all components uniformly. It costs you safety, however, because clients may try to do
meaningless things like add and remove objects from leaves
Defining child management in the Composite class gives you safety, because any attempt to add or
remove objects from leaves will be caught at compile-time in a statically typed language. But you lost
transparency, because leaves and composites have different interface.
Sample Code
class Equipment
{
public Equipment(String);
public String name() { return name; }
public abstract Watt Power();
public abstract Currency NetPrice();
public abstract Currency DiscountPrice();
public abstract void Add(Equipment*);
public abstract void Remove(Equipment*);
public abstract Equipment*
CreateIterator();
private String
name;
};
Equipment such as computer and stereo components are often organized into part-whole or containment
hierarchies
Equipment class defines an interface fro all equipment in the part-whole hierarchy.
Subclasses of Equipment might include Leaf classes that represent disk drives, integrated circuits, and
switches.
CompositeEquipment is the base class for equipment that contains other equipment
It is a composite class
It is a subclass of Equipment
Applicability
Use the Whole-Part 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.
Consequences
Advantages
Changeability of Parts
Whole encapsulates the Parts and thus conceals them from its client
Separation of concerns
Reusability
Primitive objects can be composed into more complex objects, which in turn can be composed,
and so on recursively.
Newly defined Composite or Leaf subclasses work automatically with existing structures and client
code.
Disadvantages
Makes your design overly general
The disadvantage of making it easy to add new components is that it makes it harder to restrict the
components of a composite. For example, if operations are provided in Parts ... how can we
prevent the make of some non-sense object
Wrappers are wrapper. You call somthing, something calls another thing and so on ... slow in
some case