90 likes | 235 Views
Structural Pattern: Bridge. Chapter 4 – Page 67. When the abstract interface and the concrete implementation have been set up as parallel class hierarchies, it becomes difficult to independently extend either the interface or the implementation.
E N D
Structural Pattern: Bridge Chapter 4 – Page 67 When the abstract interface and the concrete implementation have been set up as parallel class hierarchies, it becomes difficult to independently extend either the interface or the implementation. The Bridge Pattern addresses this problem by decoupling the two class hierarchies, making them orthogonal rather than parallel. In this way, the abstract interfaces can be platform-independent even when the concrete implementations are platform-dependent.
The Bridge Pattern Chapter 4 – Page 68 The Abstraction defines the client’s interface, maintaining a reference to an Implementor object, while the Refined Abstraction extends the Abstraction interface. The Implementor defines the interface for the implementation, providing primitive operations (while the Abstraction provides the higher-level operations based on these primitives). The ConcreteImplementors implement the Implementor class, providing the platform-specific implementation details.
Example: Without Bridge Pattern Chapter 4 – Page 69 Three types of shapes, with each type split into two platform-dependent subtypes. Any change to one shape type (e.g., Circle) could extend its effects to the two platform-dependent subtypes (e.g., PlatformACircle, PlatformBCircle). Any change to a platform (e.g., PlatformA) could extend its effects to all three platform-dependent shape subtypes (e.g., PlatformACircle, PlatformARectangle, PlatformATriangle).
Example: With Bridge Pattern Chapter 4 – Page 70 By decoupling the Shape abstraction from the Drawing implementor, the explosion of platform-dependent shape subclasses is avoided and the amount of redundant code is minimized. With this model, individual shape alterations and additional extensions to the Shape class will only affect the abstraction portion of the model, while platform modifications will only affect the implementor portion of the model.
Bridge Example: Time Zones Chapter 4 – Page 71 The interface base class (Time) has a pointer to the TimeImplementor base class, and each class in the interface hierarchy (i.e., the Time class and its subclasses) is responsible for populating the base class pointer with the correct concrete implementor class At that point, all requests from the client are simply delegated by the interface class to the encapsulated implementor class.
C++ Code for Time Zone Bridge Chapter 4 – Page 72 #include <iostream> #include <iomanip> #include <string> using namespace std; classTimeImplementor { public: TimeImplementor(int hr, int min) { hour = hr; minute = min; } virtual void tell() { cout << "time is " << setw(2) << hour << minute << endl; } protected: int hour, minute; }; classCivilianTimeImplementor: publicTimeImplementor { public: CivilianTimeImplementor(int hr, int min, int pm): TimeImplementor(hr, min) { if (pm) whichM = " PM"; else whichM = " AM"; } void tell() { cout << "time is " << hour << ":" << minute << whichM << endl; } protected: string whichM; };
Chapter 4 – Page 73 classMilitaryTimeImplementor: publicTimeImplementor { public: MilitaryTimeImplementor(int hr, int min, int zone): TimeImplementor(hr, min) { switch (zone) { case 5: { timezone = " Eastern Standard Time"; break; } case 6: { timezone = " Central Standard Time"; break; } case 7: { timezone = " Mountain Standard Time"; break; } case 8: { timezone = " Pacific Standard Time"; break; } } } void tell() { cout << "time is " << setw(2) << hour << minute << timezone << endl; } protected: string timezone; }; class Time { public: Time(){} Time(inthr, int min) { implementor = newTimeImplementor(hr, min); } virtual void tell() { implementor->tell(); } protected: TimeImplementor *implementor; };
classCivilianTime: public Time { public: CivilianTime(int hr, int min, int pm) { implementor = newCivilianTimeImplementor(hr, min, pm); } }; classMilitaryTime: public Time { public: MilitaryTime(int hr, int min, int zone) { implementor = newMilitaryTimeImplementor(hr, min, zone); } }; void main() { Time* times[3]; times[0] = new Time(14, 30); times[1] = newCivilianTime(2, 30, 1); times[2] = newMilitaryTime(14, 30, 6); for (int i = 0; i < 3; i++) times[i]->tell(); } Chapter 4 – Page 74
Bridge Pattern Advantages Chapter 4 – Page 75 • The Bridge Pattern is particularly useful when the structure of a class (its implementor) and what the class actually does (its abstraction) tend to change frequently. • The Bridge Pattern is most appropriate when the software model possesses two orthogonal dimensions (e.g., “what the client wants” vs. “what the platform provides”, “front-end” vs. “back-end”, “domain” vs. “infrastructure”). • By decoupling the interface from the implementation, the Bridge Pattern facilitates the independent extensibility of each and has the desirable effect of hiding details from the client.