Decouple an abstraction from its implementation so that the two can vary independently.
When an abstraction can have one of several possible implementations, the usual way to accommodate them is to use inheritance. An abstract class defines the interface to the abstraction, and concrete subclasses implement it in different ways. But this approach isn't always flexible enough. Inheritance binds an implementation to the abstraction permanently, which makes it difficult to modify, extend, and reuse abstractions and implementations independently.
Consider the implementation of a portable Window abstraction in a user interface toolkit. This abstraction should enable us to write applications that work on both the X Window System and IBM's Presentation Manager (PM), for example. Using inheritance, we could define an abstract class Window and subclasses XWindow and PMWindow that implement the Window interface for the different platforms. But this approach has two drawbacks:
The Bridge pattern addresses these problems by putting the Window abstraction and its implementation in separate class hierarchies. There is one class hierarchy for window interfaces (Window, IconWindow, TransientWindow) and a separate hierarchy for platform-specific window implementations, with WindowImp as its root. The XWindowImp subclass, for example, provides an implementation based on the X Window System.
All operations on Window subclasses are implemented in terms of abstract operations from the WindowImp interface. This decouples the window abstractions from the various platform-specific implementations. We refer to the relationship between Window and WindowImp as a bridge, because it bridges the abstraction and its implementation, letting them vary independently.
The next step is to translate the domain definitions into a number of Elisa components.
Based on the domain definitions a set of related components can be derived.
The first domain definition is a selection domain. It specifies a number of alternative domains. The implementation of selection domains is based on the concepts of categories. The following component implements the Window = IconWindow | TransientWindow :
<< implementations of: >>
The definitions in this component use patterns for dynamic type matching to select the definition rule which corresponds to the matching type. For example, the first definition rule of the BoundingBox definition test first if the type of the Shape argument is of the LineShape type. If that is the case, the corresponding LineShape function will be executed. Otherwise the following definition rule will be tried.
The IconWindow functions are defined in the following component:
. . .
. . .
The TransientWindow functions are defined in the following component:
The following component implements the WindowImp = XWindowImp | PMWindowImp :
The XWindowImps functions are defined in the following component:
. . .
. . .
The connection between Window and WindowImp can be established in the following way. Before we call any function of the Windows component we have to call the SelectWindowImp function of the WindowImp component. For example, if we want to select the PMWindowImp implementation we may do it in the following way:
Windowimp = SelectWindowImp("PMWindowImp");
With this operation Window and WindowImp are connected.
This page was last modified on 27-11-2012 17:07:02