After reviewing the five creational patterns in the previous chapter, we will now talk about another category of patterns: the structural patterns. There are seven patterns to talk about; these patterns ease the design by identifying a simple way to realize relationships between entities.
We will see how these patterns help you to encapsulate the composition of objects through the use of an interface, allowing you to conveniently abstract your system as the creational pattern does to encapsulate the creation of objects. Structural patterns highlight the use of interfaces.
You will see how the composition is designed; we will not interfere with the object itself but with the one that will transfer the structuration. This second object is strongly related to the first one. Indeed, the first object presents the interface to the client and manages its relationship with the second object, which, manages the composition and doesn't have any interfaces with clients.
One important thing to make a note of is that this structuration allows a great flexibility to your system by allowing dynamic modification of the composition. Indeed, we can substitute an object with another if both inherit the same class and use the same interface.
We can have several possible implementations. The classic way to design this is to differentiate these implementations in subclasses. In this case, we will provide an interface from where our classes will implement this interface.
This solution consists of a static composition. Indeed, once the implementation class of an object is chosen, we can no longer change it. The following diagram is the implementation of an object by heritage:
Another way is to separate the implementation in another object. The implementation parts are managed by an instance of the ConcreteImplementationA
class or by the ConcreteImplementationB
class. This reference is referred by the implementation
attribute. This instance can then be easily substituted by another instance at runtime. This composition is dynamic.
The following UML class diagram shows us clearly how to structure your objects using a dynamic composition. The ConcreteImplementation
class can be switched at runtime, without having to modify the Realization
object.
We can eventually modify the realization object, without having to modify our original object, as shown in the following diagram:
In this chapter, you'll see how to use this solution with the bridge pattern.
The discovery of the structural patterns will span three chapters. In this chapter, we will introduce you to three of them:
These three patterns provide a mechanism of adding states and behaviors dynamically, controlling the creation and access of objects, and keeping the specification and implementation separate.
The objectives of the three structural patterns that we will see in this chapter are described in the following table: