Professional Documents
Culture Documents
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
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
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
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)
A container-contents relationship
Structure
Two types of participant
Two CRC cards
Class: Whole
Responsibility:
Collaborators: Part
Class: Part
Responsibility:
Collaborators: -
Whole object forms a semantic grouping of its Parts in that it coordinates and organizes
their collaboration
The Whole uses the functionality of Parts objects for implementing services
Some of the Whole methods are just placeholders for specific Part services. When that
kind of method is invoked, the Whole calls the relevant Parts service, and returns the
result to the client
Use different relationships and further "divide" Whole-Part, the following "components"
can be inferred
Component
Implements default behavior for the interface common to all classes, as appropriate.
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)
Because the Picture interface conforms to the Graphic interface, Picture objects can
compose other Pictures recursively.
In General
Cleaning Up
The Component class should define as many common operations for Composite and Leaf classes
as possible
Principle: a class should only define operations that are meaningful to its subclass.
There are many operations that Component supports that do not seem to make sense for Leaf
classes
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?
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);
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(String);
};
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:
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
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