Presentation is loading. Please wait.

Presentation is loading. Please wait.

Structural Patterns C h a p t e r 4 – P a g e 55 StructuralPatterns Design patterns that describe how classes and objects can be combined to form larger.

Similar presentations


Presentation on theme: "Structural Patterns C h a p t e r 4 – P a g e 55 StructuralPatterns Design patterns that describe how classes and objects can be combined to form larger."— Presentation transcript:

1

2 Structural Patterns C h a p t e r 4 – P a g e 55 StructuralPatterns Design patterns that describe how classes and objects can be combined to form larger structures Adapter Intent: Convert the programming interface of one class into that of another so the two classes can work together in one program Bridge Intent: Separate the interface of a class from its implementation so that either can be varied independently Composite Intent: Develop a system in which a component may be an individual object or a collection of objects Decorator Intent: Modify the behavior of individual objects without creating a new derived class Façade Intent: Reduce the complexity of elaborate subsystems by providing a simplified interface to them Flyweight Intent: Reduce the number of similar classes by sharing their commonality and passing their differences as parameters Proxy Intent: Represent a complex object with a simpler one, thereby postponing the instantiation of the complex object until it is truly needed

3 Structural Pattern: Adapter When the client expects to interact with a class in a particular manner, it is sometimes necessary to “adapt” the interface of the class to accommodate those expectations. C h a p t e r 4 – P a g e 56 The client will call the adapter’s interface which, in turn, translates those calls into calls to the original interface of the class being adapted. This permits classes to work together in spite of incompatible interfaces.

4 The Adapter Pattern The Client has been set up to collaborate with objects that conform to the domain-specific Target interface. C h a p t e r 4 – P a g e 57 The existing Adaptee interface is adapted to the Target interface by means of the Adapter. This solution is frequently needed when an old software component offers useful functionality, but its interface is incompatible with the architecture of a new system that is being developed.

5 Non-Software Example The RoundHole client has been set up to check whether a RoundPeg target fits by checking its radius. C h a p t e r 4 – P a g e 58 The SquarePeg adaptee has a radius, not a width, but can be adapted to determine its “radius” by dividing its width by the square root of two. Note that the adaptee isn’t necessarily converted into an object of the target class, but it is adapted so the client’s needed functionality is available.

6 Primitive Software Example The client uses the (x,y) position of a Rectangle’s upper left corner and the Rectangle’s width and height to draw the Rectangle. C h a p t e r 4 – P a g e 59 The old LegacyRectangle uses the (x,y) positions of its upper left and lower right corners to draw it. The RectangleAdapter adapts the old-style drawing to the new style by converting the client’s information about the one corner, the width, and the height into the LegacyRectangle’s information about the two corners.

7 C++ Code for Rectangle Adapter C h a p t e r 4 – P a g e 60 #include using namespace std; typedef int Coordinate; typedef int Dimension; // Target Interface: Abstract Superclass class Rectangle { public: virtual void draw() = 0; }; // Adaptee: Old-style rectangle class LegacyRectangle { public: LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2) { lowX = x1; lowY = y1; highX = x2; highY = y2; cout << "LegacyRectangle: create. (" (" << highX << "," << highY << ")" << endl; } void oldDraw() { cout << "LegacyRectangle: oldDraw. (" (" << highX << "," << highY << ")" << endl; }

8 C h a p t e r 4 – P a g e 61 private: Coordinate lowX; Coordinate lowY; Coordinate highX; Coordinate highY; }; // Adapter: Rectangle is the abstract class providing the interface, while // LegacyRectangle is the concrete class providing the implementation. class RectangleAdapter: public Rectangle, private LegacyRectangle { public: RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h): LegacyRectangle(x, y, x + w, y + h) { cout << "RectangleAdapter: create. (" << x << "," << y << "), width = " << w << ", height = " << h << endl; } virtual void draw() { cout << "RectangleAdapter: draw." << endl; oldDraw(); } }; void main() { Rectangle *r = new RectangleAdapter(120, 200, 60, 40); r->draw(); }

9 C h a p t e r 4 – P a g e 62 Adapter Example: External Polymorphism Polymorphism may be implemented even if the classes are not derived from the same base class. The ExecuteAdapter adapts the three old-style classes (Moe, Larry, and Curly) to the new target style (ExecuteInterface) by converting mapping each of their respective methods (doThis, doThat, and doTheOther) to the target’s execute method.

10 C h a p t e r 4 – P a g e 63 External Polymorphism C++ Code #include using namespace std; // Target: Specifies the new interface class ExecuteInterface { public: virtual ~ExecuteInterface() {} virtual void execute() = 0; }; // Adapter: "Maps" the new interface to the legacy implementation template class ExecuteAdapter: public ExecuteInterface { public: ExecuteAdapter(TYPE *o, void(TYPE:: *m)()) { object = o; method = m; } ~ExecuteAdapter() { delete object; } void execute() { (object->*method)(); } private: TYPE *object; // ptr-to-object attribute void(TYPE:: *method)(); // ptr-to-member function attribute };

11 C h a p t e r 4 – P a g e 64 // Adaptees: Three totally incompatible classes with // no common base class and no hope of polymorphism class Moe { public: ~Moe() { cout << "Moe::destructor" << endl; } void doThis() { cout << "Moe::doThis()" << endl; } }; class Larry { public: ~Larry() { cout << "Larry::destructor" << endl; } void doThat() { cout << "Larry::doThat()" << endl; } }; class Curly { public: ~Curly() { cout << "Curly::destructor" << endl; } void doTheOther() { cout << "Curly::doTheOther()" << endl; } };

12 C h a p t e r 4 – P a g e 65 // An array of new interfaces is returned, adapted from the old implementations ExecuteInterface** initialize() { ExecuteInterface** array = new ExecuteInterface*[3]; array[0] = new ExecuteAdapter (new Moe(), &Moe::doThis); array[1] = new ExecuteAdapter (new Larry(), &Larry::doThat); array[2] = new ExecuteAdapter (new Curly(), &Curly::doTheOther); return array; } // The client uses the new interface, effectively producing an "external" polymorphism void main() { int i; ExecuteInterface** objects = initialize(); for (i = 0; i < 3; i++) objects[i]->execute(); for (i = 0; i < 3; i++) delete objects[i]; delete objects; }

13 Adapter Pattern Advantages C h a p t e r 4 – P a g e 66 The Adapter Design tends to make things work after they’ve already been designed, compelling normally incompatible designs to collaborate successfully. By adapting new interfaces to old implementations, the old code becomes reusable. In addition, the client is freed from the burden of having to account for object differences, since it treats all objects the same way. In addition, new types of objects can be accommodated without making changes to the client code.


Download ppt "Structural Patterns C h a p t e r 4 – P a g e 55 StructuralPatterns Design patterns that describe how classes and objects can be combined to form larger."

Similar presentations


Ads by Google