Continuing from the last post covering the Creational Design Pattern Secrets, now we will be covering the Structural Design Pattern Secrets. As said before this will be a quick catalog of information that are rarely highlighted about Design Patterns. Examples can be found at my Github. The catalog would be again structured in:
- When
- Effects
- Relationships
Structural Patterns
Adapter - example
When
- An interface of a class do not coincide with your needs.
- A need for a common class that connects other incompatible classes with each other.
- A need to use several classes or interfaces without utilizing inheritance.
Effects
- A single reusable class that can work with many other classes.
- The Adapter class can override some behavior of the classes it is supporting.
- The Adapter class is prone to “doing to much”.
Relationships
- Similar to the Bridge pattern which is about seperating interfaces from implementation while Adapter is about modifying interfaces to make it work with each other.
- Similar to the Decorator pattern which adds funcionality to classes without altering its interface. Supporting recursive implementation, which is not possible with Adapter.
- Similar to the Proxy pattern which creates a “proxy” to make classes work with each other.
Bridge - example
When
- Coupling of abstraction and implementation must be prevented.
- Abstractions of implementations can be mixed and match or vice versa.
- Changes to abstractions should be transparent to the clients.
Effects
- Assignment of implementation to abstractions can happen dynamically.
- Implementations and abstractions can be scaled independently.
- Clients are unaffected by changes in implementations and abstractions.
Relationships
- A Bridge can be create by the Abstract Factory pattern.
- The goal of the Adapter pattern is to make classes work together. While Bridge aims to generalize abstractions and implementations.
Composite - example
When
- Objects can be decomposed to tree structures.
- Objects and sub objects should be treated in a similar fashion by the client.
Effects
- Objects mimics structured hierarchies of its business representation.
- Simplifies the client by omitting type checking since composites are treated uniformly.
- Design can become too generic, filtering and restricting composites fallback to type checking.
Relationships
- Composites can be traversed using the Iterator pattern.
- Operations shared in the composite structure can be abstracted by the Visitor pattern.
- The links in the Chain of Responsibility and Decorator pattern is usually a composite.
Decorator - example
When
- Functionality must be added dynamically -
- And removed dynamically.
- Adding responsibilites to classes produces unecessary amount of subclasses.
Effects
- More flexible and concise addition of responsibility to objects.
- Features are added when they are needed. Classes are not prepared for the future uses making it lightweight.
- Although the decorator is transparent to the client, type checking can see it different from the what it is decorating on.
- Loss of cohesion since the responsibility is spread over little objects.
Relationships
- The Adapter pattern combines functionality while the decorator pattern adds it.
- A decorator is a Composite with one node.
- The decorator pattern changes the surface of a class, while the Strategy pattern changes the insides of it.
Facade - example
When
- A complex system can be exposed into a simple abstraction.
- Responsibility of the client on implementing abstraction of a system can be hidden.
- A system can be layered.
Effects
- Hides the complexity of a system, making it easier to implement.
- Only hides the complex system, client still has a choice to directly use the complex system.
- Reduces clients coupling to the abstraction implmentation logic.
Relationships
- Abtract Factory can be used with facade to centralize object creation.
- One instace of Facade is usually enough allowing it to be Singleton.
- The Mediator pattern is similar in a way to Facade in that it centralizes the communication logic of components. The components of the Mediator are aware of the Mediator while the Facade is trasparent to the systems it encapsulate.
Flyweight - example
When
- A large amounts of unchanging objects are used within the application.
- The storage performance suffers from the said objects.
- The state (extrinsic) or operation of the objects can be abstracted outside of it.
- Abtracting the state (extrinsic) allows objects to be shared.
- Absence of type checking of the said objects.
Effects
- Reduced space consumption.
Relationships
- The Composite pattern allows optimized querying of the Flyweight objects by representing them in a tree structure.
- Large amounts of State and Strategy objects can be represented as Flyweights.
Proxy - example
When
- Object creation can be deferred for responsiveness.
- Access restrictions must be imposed to objects.
- Objects being used must be tracked for caching.
Effects
- Object accessing and creation is optimized.
- A layer of safety is added to the object being proxied.
Relationships
- The proxy pattern rivals the Adapter pattern. The proxy pattern copies the subject (class) interface while the Adapter pattern created a new interface to connect subjects.
- The proxy patter also rivals the Decorator pattern. The proxy pattern controls access to the subject while the Decorator pattern adds functionalities to the subjects.