Composite Design Pattern
What
meant to allow treating individual objects and compositions of objects, or “composites” in the same way.
is a partitioning design pattern and describes a group of objects that is treated the same way as a single instance of the same type of object
lets you compose objects into tree structures and then work with these structures as if they were individual objects.
It can be viewed as a tree structure made up of types that inherit a base type, and it can represent a single part or a whole hierarchy of objects.
component
is the base interface for all the objects in the composition. It should be either an interface or an abstract class with the common methods to manage the child composites.
leaf
implements the default behavior of the base component. It doesn't contain a reference to the other objects.
composite/container
has leaf elements. It implements the base component methods and defines the child-related operations.
is an element that has sub-elements: leaves or other containers.
Upon receiving a request, a container delegates the work to its sub-elements, processes intermediate results and then returns the final result to the client.
client
has access to the composition elements by using the base component object.
-
When to use
when the core model of your app can be represented as a tree.
when you want the client code to treat both simple and complex elements uniformly.
when clients need to ignore the difference between compositions of objects and individual objects.
find that they are using multiple objects in the same way, and often have nearly identical code to handle each of them, then composite is a good choice, it is less complex in this situation to treat primitives and composites as homogeneous.
Advantages
You can work with complex tree structures more conveniently: use polymorphism and recursion to your advantage
You can introduce new element types into the app without breaking the existing code, which now works with the object tree.
Drawbacks
It might be difficult to provide a common interface for classes whose functionality differs too much. In certain scenarios, you’d need to overgeneralize the component interface, making it harder to comprehend.
Comparisons with other patterns
You can use Builder when creating complex Composite trees because you can program its construction steps to work recursively.
Chain of Responsibility is often used in conjunction with Composite.
In this case, when a leaf component gets a request, it may pass it through the chain of all of the parent components down to the root of the object tree.
You can use Iterators to traverse Composite trees.
You can use Visitor to execute an operation over an entire Composite tree.
You can implement shared leaf nodes of the Composite tree as Flyweights to save some RAM
Composite and Decorator have similar structure diagrams since both rely on recursive composition to organize an open-ended number of objects.
A Decorator is like a Composite but only has one child component. There’s another significant difference: Decorator adds additional responsibilities to the wrapped object, while Composite just “sums up” its children’s results.
the patterns can also cooperate: you can use Decorator to extend the behavior of a specific object in the Composite tree.
Designs that make heavy use of Composite and Decorator can often benefit from using Prototype. Applying the pattern lets you clone complex structures instead of re-constructing them from scratch.
Last updated
Was this helpful?