// Purpose. Bridge class DateImp; // // Discussion. Even though Date has class Date { // a clean interface and a well encap- public: // sulated implementation, the client Date( int y, int m, int d ); // still has to recompile if the class ~Date(); // architect changes his/her mind. void output(); // Instead, create a wrapper (or inter- static void setImp( char* t ) { // face) class that contains and dele- strcpy( impType_, t ); } // gates to a body (or implementation) private: // class. Client can now specify at DateImp* rep_; // run-time exactly what s/he wants. static char impType_[10]; }; #include char Date::impType_[] = "Ok"; #include class DateImp { public: class Date { virtual void output() = 0; }; public: Date( int y, int m, int d ); class DateOk : public DateImp { void output(); public: DateOk( int y, int m, int d ); private: void output(); private: #ifdef OK int year_, month_, day_; int year_, month_, day_; }; #endif class DateAA : public DateImp { #ifdef AA public: int toJulian(int,int,int); DateAA( int y, int m, int d ); char* fromJulian(void); void output(); int julian_; private: int year_; int toJulian(int,int,int); static int dayTable_[2][13]; char* fromJulian(void); #endif int julian_; int year_; }; static int dayTable_[2][13]; }; #ifdef OK void Date::output() { Date::Date( int y, int m, int d ) { char buf[20]; if ( ! strcmp( impType_, "Ok" )) int year = year_ - (year_/100*100); rep_ = new DateOk( y, m, d ); sprintf( buf, "%02d%02d%02d", else year, month_, day_ ); rep_ = new DateAA( y, m, d ); cout << buf << " "; } } #endif Date::~Date() { delete rep_; } void Date::output() { rep_->output(); } #ifdef AA void Date::output() { #include "bridge2.inc" cout << fromJulian() << " "; } #endif void main( void ) { #include "bridge1.inc" Date d1( 1996, 2, 29 ); Date d2( 1996, 2, 30 ); void main( void ) Date::setImp( "AA" ); { Date d3( 1996, 2, 29 ); Date d1( 1996, 2, 29 ); Date d4( 1996, 2, 30 ); Date d2( 1996, 2, 30 ); d1.output(); d2.output(); d1.output(); cout << endl; d2.output(); d3.output(); d4.output(); cout << endl; cout << endl; } } // 960229 960230 // 960229 960230 // 960229 960301 // 960229 960301 // Purpose. Bridge design pattern demo // // Discussion. The motivation is to decouple the Time interface from the // Time implementation, while still allowing the abstraction and the // realization to each be modelled with their own inheritance hierarchy. // The implementation classes below are straight-forward. The interface // classes are a little more subtle. Routinely, a Bridge pattern // interface hierarchy "hasa" implementation class. Here the interface // base class "hasa" a pointer to the implementation base class, and each // class in the interface hierarchy is responsible for populating the base // class pointer with the correct concrete implementation class. Then all // requests from the client are simply delegated by the interface class to // the encapsulated implementation class. #include #include #include class TimeImp { public: TimeImp( int hr, int min ) { hr_ = hr; min_ = min; } virtual void tell() { cout << "time is " << setw(2) << setfill(48) << hr_ << min_ << endl; } protected: int hr_, min_; }; class CivilianTimeImp : public TimeImp { public: CivilianTimeImp( int hr, int min, int pm ) : TimeImp( hr, min ) { if (pm) strcpy( whichM_, " PM" ); else strcpy( whichM_, " AM" ); } /* virtual */ void tell() { cout << "time is " << hr_ << ":" << min_ << whichM_ << endl; } protected: char whichM_[4]; }; class ZuluTimeImp : public TimeImp { public: ZuluTimeImp( int hr, int min, int zone ) : TimeImp( hr, min ) { if (zone == 5) strcpy( zone_, " Eastern Standard Time" ); else if (zone == 6) strcpy( zone_, " Central Standard Time" ); } /* virtual */ void tell() { cout << "time is " << setw(2) << setfill(48) << hr_ << min_ << zone_ << endl; } protected: char zone_[30]; }; class Time { public: Time() { } Time( int hr, int min ) { imp_ = new TimeImp( hr, min ); } virtual void tell() { imp_->tell(); } protected: TimeImp* imp_; }; class CivilianTime : public Time { public: CivilianTime( int hr, int min, int pm ) { imp_ = new CivilianTimeImp( hr, min, pm ); } }; class ZuluTime : public Time { public: ZuluTime( int hr, int min, int zone ) { imp_ = new ZuluTimeImp( hr, min, zone ); } }; void main() { Time* times[3]; times[0] = new Time( 14, 30 ); times[1] = new CivilianTime( 2, 30, 1 ); times[2] = new ZuluTime( 14, 30, 6 ); for (int i=0; i < 3; i++) times[i]->tell(); } // time is 1430 // time is 2:30 PM // time is 1430 Central Standard Time