Adapter Pattern: Pluggable Adapters, Implementation, and Bridge Pattern
This page continues the Adapter pattern discussion with pluggable adapter variants and full C++ implementation examples, then introduces the Bridge pattern — a structural pattern that decouples an abstraction from its implementation so both can vary independently. The page also begins introducing the Composite pattern.
Key Concepts
Pluggable adapters use a "narrow interface" — the smallest subset of Adaptee operations needed for adaptation — making the adapter easier to build
Three pluggable adapter approaches: (a) abstract operations in the Target class that subclasses implement, (b) delegate objects that receive forwarded requests, (c) parameterized adapters using blocks/closures
Class adapter uses multiple inheritance: public inheritance for the Target interface, private inheritance for the Adaptee implementation
Object adapter uses composition: holds a pointer/reference to the Adaptee, forwarding calls to it — more flexible because it works with Adaptee subclasses
Bridge pattern separates abstraction hierarchy from implementation hierarchy, connected by a reference (the "bridge")
Bridge eliminates class explosion: without it, M abstraction kinds × N platforms = M×N classes; with it, M + N classes
Bridge decouples at compile-time too — changing an implementation class doesn't require recompiling the abstraction or its clients
Adapter vs Bridge: Adapter retrofits compatibility between existing interfaces; Bridge is designed up-front to allow independent variation
Bridge vs Decorator: Decorator enhances without changing the interface and supports recursive composition; Bridge separates interface from implementation
Bridge vs Proxy: Proxy provides a surrogate without changing the interface
Adapter → Factory Method: CreateManipulator() in TextShape is a Factory Method that creates the appropriate Manipulator
Bridge → Abstract Factory: An Abstract Factory can create and configure the correct Implementor for a Bridge
Bridge vs Adapter: Both involve indirection to another object, but Adapter is applied after design (retrofit), Bridge is applied up-front (planned separation)
Bridge vs Decorator: Decorator preserves interface and supports recursive wrapping; Bridge separates two independent hierarchies
Bridge → Singleton: The WindowSystemFactory in the example is a Singleton
Composite (introduced at end): Composes objects into tree structures for part-whole hierarchies — enables uniform treatment of individual and composite objects
Exam-Relevant Points
Narrow interface is the key to pluggable adapters — minimize the operations the Adaptee must support
Three pluggable adapter strategies: abstract operations (subclassing), delegate objects (composition), parameterized (blocks/closures) — know the trade-offs of each
Object adapter is more flexible than class adapter because it works with any subclass of the Adaptee
Class adapter cannot adapt a class and all its subclasses; object adapter can
Bridge solves the class explosion problem (nested generalizations / M×N proliferation)
The Bridge Implementor interface need not match the Abstraction interface — typically Implementor provides primitives, Abstraction provides higher-level operations
A degenerate Bridge with only one Implementor is still useful for hiding implementation and avoiding recompilation (C++ "Cheshire Cat" / pimpl idiom)
Bridge implementation can be selected or switched at run-time
Handle/Body idiom (Coplien) is a form of Bridge with reference counting for shared implementations
Multiple inheritance cannot implement a true Bridge in C++ because it creates a static binding between interface and implementation
Key distinction: Adapter = make things work together after the fact; Bridge = design for independent variation from the start; Decorator = add responsibilities transparently; Proxy = control access without changing interface