Pattern: Bridge

Synopsis

Seperate a complex abstraction from its implementation(s) so that the two can vary Independantly.

Context

Suppose that you want to create a portable Window abstraction (swing). You would need to have several types of Windows such as dialogs, popup menus, frames, etc. To create these Window types you would probably want to use subclassing. You would also need to implement these Window types. With one subclassed implementation for X, one for MS Windows for each subclass of Window you would end up with a very large class hierarchy.

Forces

When you have a complicated abstraction that includes numberous subclasses and several possible implementations all of which will likely need to change there is a problem with any change higher up in the class hierarchy will have ripple-down effects.

Solution

Define a base class Abstraction that defines basic operations. Then define the subclasses of the base class with all of the subclass' functions implemented in terms of the basic operations defined in the Abstraction. Then define an Implementor interface. Each implementation will implement the Implementor interface. Then have the methods of the Abstraction class call corresponding methods in the Implementor class.

Consequences

The interface and its implementation have been decoupled. This means that the implementation can be configured and changed at run-time. This also removes any compile-time dependancies on the implementation classes. Also the bridge pattern effectively layers that portion of the code since all a client need know about is Abstraction and Implementor.

Extensibility is also improved since Abstraction and Implementor can be extended independantly of each other.

Implementation details are hidden from clients of Abstraction.

Implementation

If there is only one implementation then an abstract Implementor isn't needed. This is a simple case of the Bridge pattern but it can be useful since changing the implementation won't require a recompilation of the Abstraction.

Determining when and how to create an instance of ConcreteImplementor is something that needs to be considered carefully. Possible implementations include: having Abstraction create the instance based on arguments to its constructor, or have the Abstraction create a default then change the instance as needed, a factory object could also be introduced to the system, or perhaps the client can set the instance itself and pass it to the Abstraction.

Multiple inheritance (via interfaces) can be used to combine the interface with its implementation if needed.

See the example solution here.

Related Patterns

AbstractFactory can be used to create/configure a bridge.

Adapter is a way to handle a similar problem after the design is complete. Bridges are intended more for up-front design of a system.


Modified: 20-Apr-2004
Owen Smith