The Bridge Pattern (Structural) “All problems in computer science can be solved by another level of indirection.” – Butler Lampson ©SoftMoore Consulting Slide 1
Jan 19, 2016
The Bridge Pattern(Structural)
“All problems in computer science can be solved by another level of indirection.” – Butler Lampson
©SoftMoore Consulting Slide 1
Motivation
• Sometimes an abstraction should have different implementations– a persistence framework over different platforms using either
relational databases or file system structures (files and folders).– a GUI framework with implementations for Microsoft Windows,
Linux, or Apple OS X
• How do we design classes so that clients can be written to depend on the abstraction and not the implementation details?
©SoftMoore Consulting Slide 2
Bridge Pattern: Basic Idea
• Divide an abstraction into two classes.– High-level class that provides an interface to clients– Implementation class, often with additional semantics
• High-level class contains a reference (pointer) to its implementation
• Operations on objects of the high-level class are delegated to the implementation
• Clients depend on the high-level class, not the implementation
©SoftMoore Consulting Slide 3
Bridge Pattern
• Intent: Decouple an abstraction from its implementation so that the two can vary independently.
• Also Known As: Handle/Body
©SoftMoore Consulting Slide 4
Bridge Pattern
©SoftMoore Consulting Slide 5
Abstraction
operation()
imp.operationImp()
imp
1
RefinedAbstraction
Structure
Implementor
operationImp()
ConcreteImplementorA
operationImp()
ConcreteImplementorB
operationImp()
©SoftMoore Consulting
Bridge Pattern(continued)
Participants
• Abstraction– defines the abstraction’s interface– maintains a reference to an object of type Implementor
(one of the ConcreteImplementors)
• RefinedAbstraction– extends the interface defined by Abstraction
• Implementor– defines the interface for implementation classes. Typically the
implementor provides only primitive operations, and Abstraction defines higher-level operations based on the primitives
Slide 6
©SoftMoore Consulting
Bridge Pattern(continued)
Participants (continued)
• ConcreteImplementor– implements the Implementor interface and defines its concrete
implementation
Slide 7
Bridge Pattern(continued)
Consequences
• Implementation of an abstraction can be modified or extended without affecting the clients.
• Eliminates compile-time dependencies.
• Hides implementation details from the client.(Client depends only on the abstraction, not the implementation.)
• One implementation can be shared by several objects.
©SoftMoore Consulting Slide 8
The Degenerate Bridge
• Only one concrete implementation class– Implementor class is not abstract
• Still useful to avoid recompilation of the abstraction and allow a shared implementation
Slide 9©SoftMoore Consulting
©SoftMoore Consulting
Bridge Pattern in Java – AWT
• Java applications can run on different platforms. To improve portability, client code should be able to create a UI Component without committing to a concrete implementation.
• Java uses the Bridge Pattern to separate components and component peers. An AWT component has a corresponding peer with which it can communicate.
• The components and component peers are represented as two different class hierarchies.– java.awt.Button – java.awt.peer.ButtonPeer
• The peer class is platform specific.
Slide 10
Case Study: Mutable Strings in C++with Shared Implementations
• Strings are common to most applications, but C provides only primitive support. Object-oriented languages like C++ provide the opportunity to “raise” the level of usage with respect to user-defined types.
• How should a string class be designed? Initially a class should be designed from the point of view of its clients. A string class should be easy to use and it should support all common string processing.
©SoftMoore Consulting Slide 11
Examples: Using a String Class
String s1("object"); // initialization
String s2 = "oriented"; // initialization
String s3; // default constructor
cout << s1 + "-" + s2; // I/O and concatenation
s3 = s1 + "ive"; // assignment
if (s3 <= s2) ... // string comparison
... // other operations such as length, substring
// search, substring extraction, etc.
©SoftMoore Consulting Slide 12
String Class: Version 1
class String { public: String(); // default constructor String(const char*); // conversion constructor String(const String&); // copy constructor ~String(); const String& operator = (const String&); friend String operator + (const String&, const String&); ... // other member functions operator const char* () const; // conversion operator friend bool operator == (const String&, const String&); ... // other comparison operators int length() const; friend istream& operator >> (istream&, String&); private: ... // TBD };
©SoftMoore Consulting Slide 13
Representing Strings
• Now we turn to the “inside” view of strings, the representation details. To support dynamic strings, consider using a pointer to a null-terminated array of characters. class String { public: ... // member functions as before private: char* text; };
©SoftMoore Consulting Slide 14
Representing Strings(continued)
• Member functions could be defined using C’s string functions. Many are candidates for inline definitions. To preserve common semantics, assignment and constructors would need to make separate copies of the character array pointed to by text.
• This representation can be visualized as follows:String s("Hello");
©SoftMoore Consulting Slide 15
texts H e l l o \0
Sample Member Function Definitions
inline bool operator == (const String& s1, const String& s2) { return (strcmp(s1.text, s2.text) == 0); }
...
©SoftMoore Consulting Slide 16
Sample Member Function Definitions(continued)
const String& String::operator = (const String& s) { if(this != &s) // beware s = s { if (text) delete[] text; int len = strlen(s.text); if (len > 0) { text = new char[len + 1]; assert(text != 0); strcpy(text, s.text); } else text = 0; } return *this; }
©SoftMoore Consulting Slide 17
Comments on the Designof the String Class
• Assuming sufficient member functions are provided to support common string processing, this class would provide a safe, easy-to-use interface to its clients.
• For most string applications, the extra coping involved with assignment and initialization would cause a noticeable run-time penalty. The entire array of characters is replicated just to store redundant information.
©SoftMoore Consulting Slide 18
Abstraction versus Implementation
• It is important to distinguish between the abstraction provided by the class interface to its clients and the implementation of that abstraction.
• Under most circumstances, it is acceptable for instances to “share” information as long as changes to one instance don’t violate the integrity of the other.
©SoftMoore Consulting Slide 19
Applying the Bridge Pattern
• Let’s redesign the string class with the following goals– preserve safe, easy-to-use abstract interface– improve overall efficiency by reducing the need for copying
character arrays (allowed shared representations)
• Approach– bridge pattern– reference (use) counts– copy on update
©SoftMoore Consulting Slide 20
String Class: Version 2
class StringRep; class String { public: ... // member functions as before private: StringRep* rep; // handle to string representation };
©SoftMoore Consulting Slide 21
String Class: Version 2(continued)
class StringRep { friend class String; private: // used only by class String StringRep(); // default constructor StringRep(const char*); // conversion constructor ~StringRep();
... // additional member functions as required
int use_count; // remembers the number of // users of a representation char* text; };©SoftMoore Consulting Slide 22
String Class: Version 2(continued)
• This new design can be visualized as follows:
©SoftMoore Consulting Slide 23
String
...
StringRep
useCount : inttext : char*
...
repClass Level * 1
s1 : String
s2 : String
s3 : String
: StringRep
useCount = 3text = “Hello, World”
Object Level
Implementing Version 2
• Version 2 allows different strings to share a common representation. But what if one of the strings is updated?s1 = s1 + " world."; // concatenation
• To preserve the integrity of the other strings sharing the representation, we would have to detach s1 from the shared representation and create a new representation for it. In effect we delay copying until the representation for a string object is modified (sometimes referred to as copy-on-write or copy-on-update) and the reference count for the representation is greater than 1.
©SoftMoore Consulting Slide 24
©SoftMoore Consulting
Comments on Version 2
• Version 2 requires more work on the part of the implementor of the class in order to manage reference counts.
• Version 2 preserves the safe, easy-to-use interface of version 1. (Clients of version 2 are generally oblivious to the fact that the implementation is different.)
• Version 2 will perform– faster in string processing applications that involve a lot of string
copying (assignment, copy constructor, etc.).– more slowly for applications that involve very little copying since
some time is spent managing use counts.
Slide 25
©SoftMoore Consulting
Comments on Version 2(continued)
• If run-time performance is critical, we could have both versions. Since both versions provide equivalent public interfaces to their clients, the two classes would logically be interchangeable in applications.
Slide 26
©SoftMoore Consulting
Related Patterns
• An Abstract Factory can create and configure a particular Bridge.
• Strategy and Bridge have similar UML diagram, but they differ in their intent. Strategy is mainly concerned in encapsulating algorithms, whereas Bridge decouples the abstraction from the implementation in order to provide different implementations for the same abstraction.
• A Proxy is essentially a Bridge with only one implementation, where the abstraction and implementation share the same interface.
Slide 27
©SoftMoore Consulting
References
• Bridge pattern (Wikipedia)https://en.wikipedia.org/wiki/Bridge_pattern
• Bridge Pattern (Object-Oriented Design)http://www.oodesign.com/bridge-pattern.html
• Bridge Design Pattern (SourceMaking)https://sourcemaking.com/design_patterns/bridge
Slide 28