Easy patterns: Composite

Ruslan Malogulko
ITNEXT
Published in
3 min readOct 13, 2018

--

This article is created in continuation of easy patterns series description and presents a Composite pattern which solves the problem of how to use recursive composition among set of different objects so clients don’t have to make this distinction.

Creational patterns:

Simple Factory

Factory method

Builder

Singleton

Abstract factory

Prototype

Structural patterns:

Adapter

Decorator

Bridge

Composite (this article)

Facade

Flyweight

Proxy

Behavioral patterns:

Visitor

Mediator

Observer

Memento

Iterator

Chain Of Responsibility

Strategy

State

The main essence

The Composite pattern helps to operate separate objects in unified order. This is possible due to special class object which declares common representation operations for all participants in composition set.

This pattern includes three main roles:

  • Component — declares the interface for objects in the composition and implements the default behavior (based on Composite)
  • Leaf — represents primitive objects in the composition
  • Composite — implements child-related operations in the Component interface and stores Leaf (primitive) objects.

Clients are using the Component interface to interact with objects in the composition set. If the recipient is a simple object (Leaf), then request is handled directly by this simple object. If the recipient is a Composite, it usually forwards request to child components. For composite is also typical to perform some pre- and post-hook operations.

Example of use

In this example we handle getting an average salary of employees for a concrete organization. An organization stores employees in an array and can count average salary of all employees.

This is a simple representation of usage, when organization can store only typical employee (with name and getSalary method).

To feel all the power of a pattern just imagine a situation when a parent organization can store not only employees but also a child organizations. All what is needed for that is just to implement getSalary method for such child organization which would return an average salary of its internal employees. In such way calling avgSalary on parent organization wouldn’t be broken and a result would be the average salary over all the emloyees whether working on parent organization directly or through child organizations.

Profit

This pattern makes the client simple. Clients can work with individual either composite structure in similar manner. This makes client code simpler because it avoids having to write case statement functions over the classes for simple and complex objects.

This pattern makes it easy to add new kinds of components. Newly created items work automatically with existing structures and client code.

Weak places

From the other hand this pattern can make your design more generic. It makes harder to restrict the components of a composite (for example you want a composite to include only certain components). This approach enforces you to use run-time checks instead.

Conclusion

The Composite pattern are often used in tandem with other patterns like:

  • Decorator — when used together with a Composite they usually have a common parent, so decorators will have to support the Component interface like Add, Remove, etc.
  • Flyweight — lets you share components.
  • Iterator — lets you traversing composites.
  • Visitor — localizes operations and behavior that in other case would be distributed across composite classes.

If you found this article helpful, please hit the 👏 button and feel free to comment below!

--

--