By Steven Black
|
Context |
You are designing a new class, or adapting an existing class to make it more reusable. You anticipate future extensions to object's form or function and you want to avoid extending a class hierarchy for the sake of new implementations. perhaps you'd like to choose a specific behavior at run-time. |
|
Problem |
To achieve reuse, some classes need to adapt either their implementations, their interfaces, or both. How to structure a class so that either (or both) can be easily modified? |
|
Forces |
|
|
Solution |
Decouple an object's public interface ("form") from its implementation (its "function"), using two (or
more) objects where otherwise one might less flexibly suffice.
Separate a class's interface from its implementation by making each a separate but tightly coupled objects. This way each can be varied independently of the other. The workings among the players in a Bridge should be direct and simple: the interface object forwards client requests to the appropriate implementation object. Tight coupling within the Bridge structure is both common and desirable. The tight coupling is much easier to manage when all the implementation objects come from the same class, as illustrated in the Codebook example illustrated below. |
|
Resulting Context |
A Bridge is a decoupling of an abstraction (interface) from its implementation so the two can vary independently. Bridges are scale-independent structures that apply in many object oriented situations. A Bridge also serves as an atomic element player in other design patterns. |
|
Rationale |
The usual way to manage the requirement for different interface or implementation is by extending the
class hierarchy using inheritance. After all, inheritance is usually the first mechanism most folks use
to reuse their classes. And why not? In the early going, inheritance is always a big success.
At the limit, however, inheritance leads to sclerosis -- inheritance doesn't scale particularly well. Simple, single-object inheritance binds interface and implementation - you only have one package to transform into a subclass. This means that interface and implementation aspects cannot be independently varied without extending the class hierarchy. But class hierarchies naturally loses their inherent adaptability with size and as the number and variety of clients increases. Why? -- side effects, partly. The probability of change side-effects in clients increases with the number and variety of those clients, and correspondingly with the current state of the hierarchy. In a giant class hierarchy, making a small change near the top can potentially be very expensive. This will occasionally limit what can be reasonably done at a given level in a class hierarchy. The Bridge pattern mitigates class sclerosis by decoupling interfaces from implementations, and putting the abstraction and implementation in separate class hierarchies. This allows the interface and implementation classes to vary independently, and the inherent substitutability of subclasses makes the structure intrinsically adaptable (and hence reusable). The Bridge in all this is the relationship between the interface and the implementation objects that together form a self-supporting system. |
|
A.K.A. |
"Handle And Body" and "Envelope And Letter". Those descriptive names are good - the dual-object nature of Bridge patterns is well conveyed, as is the tight coupling usually found between the programming interface and implementation objects. |