Bridge pattern = Insulation
- encapsulation
- implementation details (type, data, or function) are not accessible
programmatically through the interface of the component - a logical property
of design
- insulation
- implementation details (type, data, or function) can be altered without
forcing clients of the component to recompile - a physical property of design
Carroll and Ellis - inheritance hierarchy styles
The design of a reusable library can be based on one of several inheritance
hierarchy styles or on a combination of styles. These include:
- Direct hierarchy
Design as usual - map domain types directly to C++ classes.
Intermixes interface and implementation. Minimizes the number of
classes. Implementation changes generally cause link
incompatiblilities.
- Interfaced hierarchy
Mirror every direct hierarchy class with a pure abstract class
(interface only). This doubles the number of classes but improves
extensibility and link compatibility.
- Interfaced + Factory hierarchy
Add an "object factory" to the interfaced hierarchy. Each factory
encapsulates all client creation services (clients never "new" their
own instances). Clients can now write programs that will need no
recompiling whatsoever to upgrade to a new release of the library.
- Handle hierarchy
Wrap every direct hierarchy class with a "handle" class. The
original class becomes a hidden "body" or "representation" class. Each
"handle" class is a thin veneer that simply delegates all user requests
to its contained "body" class. Any change to the implementation of a
"body" class will be link compatible for clients of its encapsulating
"handle" class. Not as extensible as Direct and Interfaced
hierarchies.
- Interfaced Handle hierarchy
Add a third set of interface classes (body classes are the first
set, and handle classes are the second set) to reinstate some amount of
extensibility.
Although a direct inheritance hierarchy is the easiest style to implement
and understand as well as the most efficient, interfaced hierarchies,
object factories, and handle hierarchies facilitate link compatibility
between releases of a library. Further, interfaced hierarchies increase
a library's extensibility. The table summarizes the most important
differences among the hierarchy styles. As always, no single design is
best for all libraries. Library designers must decide which is the
best choice for their library and their users.
Hierarchy style |
Complexity |
Efficiency |
Extensibility |
Link compatibility |
---|
Direct |
simple |
good |
mediocre |
minimal |
Interfaced |
complex |
reduced |
good |
partial |
Interfaced + Factory |
complex |
reduced |
good |
total |
Handle |
simple |
reduced |
poor |
total |
Interfaced Handle |
complex |
reduced |
good |
total |
Lakos - insulation techniques
Handle
- use when concrete usage of the class predominates
- use when you are already creating instances of the class
Interfaced
- allows the interface to be subscribed to without picking up any
implementation baggage
- use when abstract usage of the class predominates
- use when you are only referring to the class via the base class
Meyers - insulation techniques
Handle
- defer to contained pointer
- easy to switch between Handle and Body classes with typedef
- Handle operations can't be inlined
- must pay for heap allocation of Body instance
- difficult to extend with inheritance
Interfaced
- defer to v-table pointer
- good with inheritance
- Interface operations can't be inlined
- must pay for heap allocation of derived instances
- no easy way to switch between Interface and derived classes