SDSU CS 635: Advanced Object-Oriented Design & Programming
Spring Semester, 1998
Bridge

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Apr-98

Contents of Doc 22, Bridge

Referencesslide # 1
Bridge slide # 2
...Applicability slide # 4
...Bridge and Other Patterns slide # 12

References

Design Patterns: Elements of Resuable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison Wesley, 1995 pp 151-162

Advanced C++: Programming Styles and Idioms, James Coplien, 1992, pp 58-72


Doc 22, Bridge Slide # 2

Bridge


Decouple the abstraction from its implementation

This allows the implementation to vary from its abstraction

The abstraction defines and implements the interface

All operations in the abstraction call method(s) its implementation object

Bridge

Doc 22, Bridge Slide # 3
What is Wrong with Using an Interface?



Make Abstraction a pure abstract class

In client code:

Abstraction widget = new ConcreteImplA();
widget.operation();

This will seperate the abstraction from the implementation

We can vary the implementation!


Doc 22, Bridge Slide # 4

Applicability


Use the Bridge pattern when


Doc 22, Bridge Slide # 5
Binding between abstraction & implementation

In the Bridge pattern:

an abstraction can use different implementations

an implementation can be used in different abstraction
Hide implementation from clients

Using just an interface the client can cheat!

     Abstraction widget = new ConcreteImplA();
     widget.operation();

     ((ConcreteImplA) widget).concreteOperation();

In the Bridge pattern the client code can not access the implementation

Java uses Bridge to prevent programmer from accessing platform specific implementations of interface widgets, etc.

peer = implementation

     public synchronized void setCursor(Cursor cursor) {
          this.cursor = cursor;
          ComponentPeer peer = this.peer;
          if (peer != null) {
               peer.setCursor(cursor);
          }
     }

Doc 22, Bridge Slide # 6
Abstractions & Imps independently subclassable

Start with Widow interface and two implementations:



Now what do we do if we need some more types of windows: say IconWindow and DialogWindow?




Doc 22, Bridge Slide # 7
The Bridge pattern provides a cleaner solution



IconWindow and DialogWindow will add functionality to or modify existing functionality of Window

Methods in IconWindow and DialogWindow need to use the implementation methods to provide the new/modified functionality

This means that the WindowImp interface must provide the base functionality for window implementation

This does not mean that WindowImp interface must explicitly provide an iconifyWindow method


Doc 22, Bridge Slide # 8
Share an implementation among multiple objects

Example use is creating smart pointers in C++


String contains a StringRep object

StringRep which holds the text and reference count

String passes actual string operations to StringRep object

String handles pointer operations and deleting StringRep object when reference count reaches zero

String a( "cat");
String b( "dog");
String c( "mouse");
a = b;
a = c;


Doc 22, Bridge Slide # 9
C++ Implementation From Coplien
class StringRep     {
     friend String;
          
     private:
          char *text;
          int refCount;
               
          StringRep()     { *(text = new char[1] = '\0'; }
               
          StringRep( const StringRep& s )     {
               ::strcpy( text = new char[::strlen(s.text) + 1, s.text);
          }
               
          StringRep( const char *s)     {
               ::strcpy( text = new char[::strlen(s) + 1, s);
          }
               
          StringRep( char** const *r)     {
               text = *r;
               *r = 0;
               refCount = 1;;
          }
               
          ~StringRep()     { delete[] text; }
               
          int length() const     { return ::strlen( text ); }
               
          void print() const     { ::printf("%s\n", text ); }
     }


Doc 22, Bridge Slide # 10
class String     {
     friend StringRep

     public:
          String operator+(const String& add) const {
               return *imp + add;
          }

          StringRep* operator->() const     { return imp; }

          String()     { (imp = new StringRep()) -> refCount = 1;     }

          String(const char* charStr)     {
               (imp = new StringRep(charStr)) -> refCount = 1;
          }

          String operater=( const String& q)     {
               (imp->refCount)--;
               if (imp->refCount <= 0 &&
                     imp != q.imp )
                    delete imp;

               imp = q.imp;
               (imp->refCount)++;
               return *this;
          }

          ~String()     {
               (imp->refCount)--;
               if (imp->refCount <= 0 ) delete imp;
          }

     private:
          String(char** r)  {imp = new StringRep(r);}
          StringRep *imp;
};

Doc 22, Bridge Slide # 11
Using Counter Pointer Classes
int main()
{
     String a( "abcd");
     String b( "efgh");

     printf( "a is ");
     a->print();

     printf( "b is ");
     b->print();

     printf( "length of b is %d\n", b-<length() );
     
     printf( " a + b ");
     (a+b)->print();
}

Doc 22, Bridge Slide # 12

Bridge and Other Patterns


Adapter
Used to make unrelated classes work together
Usually applied after they're designed

State ?

Strategy ?


visitors since 16-Apr-98