Composite
Compose objects into tree structures to represent part-whole hierar- chies. Composite lets clients treat individual objects and compositions of objects uniformly.
Last updated
Compose objects into tree structures to represent part-whole hierar- chies. Composite lets clients treat individual objects and compositions of objects uniformly.
Last updated
Composite is a design pattern that belongs to the Structural Pattern group. Composite Pattern is a synthesis of related components to create a larger component. It allows interactions with all objects in the sample to be similar.
Frequency of use: quite high
Composite Pattern is used when we need to process a group of similar objects in the same way as 1 object. The composite pattern arranges objects in a tree structure to represent a partial as well as the entire hierarchy. This pattern creates a class containing its own group of objects. This class provides ways to modify groups of the same object. This pattern allows the Client to write the same code to interact with this composite object, regardless of whether it is an individual object or a collection of objects.
For example, you have two types of objects: Products and Boxes. A Box can contain multiple Products as well as several smaller Boxes. These Small Boxes can also hold some Products or even smaller Boxes etc
Let's say you decide to create an ordering system. How would you determine the total price of such an order? You can open all the boxes, look through all the products and then calculate the total. But this approach to program implementation requires a level of integration and complex structure.
Solution: The Composite pattern allows working with Products and Boxes through a common interface that declares a method for calculating total prices. For a box, it will go through each item in the container, ask for its price, and then return the total price for this box. The biggest benefit of this approach is that there is no need to care about the specific classes of the created objects and handle them with the same method.
The armies of most countries are structured as hierarchies. An army consists of several divisions; a division is a set of brigades, and a brigade consists of platoons, which can be broken down into squads. Finally, a squad is a small group of real soldiers. Orders are given at the top of the hierarchy and passed down to each level until every soldier knows what needs to be done.
Components in the model:
Component: is an interface or abstract class that defines the common methods required for all components participating in this template.
Leaf: is a class that implements the methods of Component - objects without children.
Composite : stores a collection of Leafs and implements Component methods. Composite implements methods defined in the Component interface by delegating processing to child components.
Client: uses Component to work with objects in Composite.
Advantage
You can work with complex tree structures more conveniently.
Open/closed principle: it is possible to instantiate new element types into the application without breaking the existing code working with the tree object.
The code can become more complex than it should be, as there are many interfaces and classes instantiated with the template.
When you want to create objects in tree structures to represent a hierarchy.
It can be difficult to provide a common interface for classes whose functionality differs so much. In certain cases, you need to overgeneralize the component interface making it harder to understand.
Use the Composite pattern when you have to implement a tree-like object structure.
The Composite pattern provides you with two basic element types that share a common interface: simple leaves and complex containers. A container can be composed of both leaves and other containers. This lets you construct a nested recursive object structure that resembles a tree.
Use the pattern when you want the client code to treat both simple and complex elements uniformly.
All elements defined by the Composite pattern share a common interface. Using this interface, the client doesn’t have to worry about the concrete class of the objects it works with.
Make sure that the core model of your app can be represented as a tree structure. Try to break it down into simple elements and containers. Remember that containers must be able to contain both simple elements and other containers.
Declare the component interface with a list of methods that make sense for both simple and complex components.
Create a leaf class to represent simple elements. A program may have multiple different leaf classes.
Create a container class to represent complex elements. In this class, provide an array field for storing references to sub-elements. The array must be able to store both leaves and containers, so make sure it’s declared with the component interface type.
While implementing the methods of the component interface, remember that a container is supposed to be delegating most of the work to sub-elements.
Finally, define the methods for adding and removal of child elements in the container.
Keep in mind that these operations can be declared in the component interface. This would violate the Interface Segregation Principle because the methods will be empty in the leaf class. However, the client will be able to treat all the elements equally, even when composing the tree.
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 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.
However, the patterns can also cooperate: you can use Decorator to extend the behavior of a specific object in the Composite tree.