Gof Design Pattern Categories
Total Page:16
File Type:pdf, Size:1020Kb
GoF Design Pattern Categories Purpose Creational Structural Behavioral Scope Class Factory Method Adapter Interpreter Template Method Object Abstract Factory Adapter Chain of Responsibility Builder Bridge Command Prototype Composite Iterator Singleton Decorator Mediator Facade Memento Proxy Observer Flyweight State Strategy Visitor Structural patterns • Structural Patterns let you compose classes or objects into larger structures Adapter Pattern • Intent • Convert the interface of a class into another interface clients expect. • Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. • Wrap an existing class with a new interface. • Also Known As • Wrapper Intermediary acts like a translator between the client and the server. E.g., Format/protocol conversions. Adapter Pattern Motivation • Sometimes a toolkit or class library can not be used because its interface is incompatible with the interface required by an application • We can not change the library interface, since we may not have its source code • Even if we did have the source code, we probably should not change the library for each domain-specific application Adapter Pattern • Motivation Structure An object adapter relies on object composition: • Delegation is used to bind an Adapter and an Adaptee • 1) Interface inheritance is use to specify the interface of the • Adapter class. • 2) Adaptee, usually called legacy system, pre-exists the Adapter. • 3) Target may be realized as an interface in Java. Structure An object adapter relies on object composition: Structure • A class adapter uses multiple inheritance to adapt one interface to another: Adapter Pattern • Applicability • Use the Adapter pattern when • you want to use an existing class, and its interface does not match the one you need. • you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces. • (object adapter only) you need to use several existing subclasses, but it's unpractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class. Participants • Target (shape) defines the domain-specific interface that Client uses. • Adapter (TextShape) adapts the interface Adaptee to the Target interface. • Adaptee (TextView) defines an existing interface that needs adapting. • Client (DrawingEditor) collaborates with objects conforming to the Target interface. Collaboration Clients call operations on an Adapter instance. In turn, the adapter calls Adaptec operations that carry out the request. Amirkabir University of Technoloy Computer Engineering slide 16 Department Adapter Pattern Consequences Class form commits to a concrete Adaptee class, so won’t work if we want to adapt a class as well as subclasses (use object form) Adapter can override Adaptee’s behavior introduces only one object; no pointer indirection required Adapter Pattern Consequences Object form allows single Adapter to work with many Adaptee subclasses; can add functionality to all Adaptees at once harder to override Adaptee behvarior – have to subclass Adaptee and make Adapter refer to the subclass Implementation • How much adapting should be done? • Simple interface conversion that just changes operation names and order of arguments • Totally different set of operations • Does the adapter provide two-way transparency? • A two-way adapter supports both the Target and the Adaptee interface. It allows an adapted object (Adapter) to appear as an Adaptee object or a Target object Implementation • Adapter should be subtype of Target • Pluggable adapters should use the narrowest definition • Abstract operations to minimize exposed interface • Delegated objects to localize behavior • Parameterized processing avoids subclasses of adaptee Related pattern • The Bridge pattern shares structure with object adapter, but diverges on intent. • Bridge is concerned with separating an object's interface from its implementation while adapter changes the interface of an existing object • The Decorator pattern does not change an object's interface, but it does support recursive composition which adapter does not. • In this way, Decorator is more flexible than adapter for dealing with functionality additions • Proxy defines surrogate for another object without changing its interface Implementation Amirkabir University of Technoloy Computer Engineering slide 22 Department Adapter • Now, let’s say you’re short on Duck objects and you’d like to use some Turkey objects in their place. • Obviously we can’t use the turkeys outright because they have a different interface. • So, let’s write an Adapter: class Adaptee { public string GetLastName() { return “Mahmoodi"; } } ------------------ interface ITarget { string GetFullName(); } class Adapter:Adaptee,ITarget { public string GetFullName() { //Adaptee a = new Adaptee(); return "Ali " + GetLastName(); } } ---------- private void button1_Click(object sender, EventArgs e) { ITarget i = new Adapter(); MessageBox.Show(i.GetFullName()); } Bridge pattern • Also Known As • Handle/Body Motivation • Problem: For some classes, we want to adapt (reuse) either their abstractions, their implementations or both. How can we structure a class so that abstractions and/or implementations can easily be modified. • Inheritance binds an implementation to the abstraction permanently, which makes it difficult to modify, extend, and reuse abstraction and implementations independently. Applicability • Need to avoid a permanent binding between an abstraction and implementation. • When abstractions and implementations should be extensible through subclassing. • When implementation changes should not impact clients. • When the implementation should be completely hidden from the client. (C++) • When you have a proliferation of classes. • When, unknown to the client, implementations are shared among objects Structure Participants & Collaborations • Abstraction (Window) - defines the abstraction's interface - maintains a reference to the Implementor forwards requests to the Implementor (collaboration) • RefinedAbstraction ((IconWindow)) - extends abstraction interface • Implementor (Windowlmp) - defines interface for implementations • ConcreteImplementor (XWindowImp, PMWindowImp) -implements Implementor interface, ie defines an implementation Consequences • Decouples interface and implementation Decoupling Abstraction and Implementor also eliminates compile-time dependencies on implementation. Changing implementation class does not require recompile of abstraction classes. • Improves extensibility Both abstraction and implementations can be extended independently • Hides implementation details from clients Implementation Issues • How, where, and when to decide which implementer to instantiate? Depends: - if Abstraction knows about all concrete implementer, then it can instantiate in the constructor. - It can start with a default and change it later - Or it can delegate the decision to another object (to an abstract factory for example) • Implementers can be shared and usage tracked. (Handle / Body) • Can’t implement a true bridge using multiple inheritance A class can inherit publicly from an abstraction and privately from an implementation, but since it is static inheritance it bind an implementation permanently to its interface Example1 Suppose I have been given the task of writing a program that will draw rectangles with either of two drawing programs. I have been told that when I instantiate a rectangle, I will know whether I should use drawing program 1 (DP1) or drawing program 2 (DP2). The rectangles are defined as two pairs of points, as represented in the following figures and the differences between the drawing programs are summarized in the following table. Example1 Example 1 My customer told me that the clients of the rectangles do not want to worry about what type of drawing program it should use. It occurs to me that since the rectangles are told what drawing program to use when instantiated, I can have two different kinds of rectangle objects: one that uses DP1 and one that uses DP2. Each would have a draw method but would implement it differently. Example1 By having an abstract class Rectangle, I take advantage of the fact that the only difference between the different types of Rectangle are how they implement the drawLine method. The V1Rectangle is implemented by having a reference to a DP1 object and using that object’s draw_a_line method. The V2Rectangle is implemented by having a reference to a DP2 object and using that object’s drawline method. However, by instantiating the right type of Rectangle, I no longer have to worry about this difference. Example 1 Java Code Fragments Example 1 Now, suppose that after completing this code, one of the inevitable requirements three (death, taxes, and changing requirements) comes my way. I am asked to support another kind of shape—this time, a circle. However, I am also given the mandate that the collection object does not want to know the difference between Rectangles and Circles. It occurs to me that I can simply extend the approach I’ve already started by adding another level to my class hierarchy. I only need to add a new class, called Shape, from which I will derive the Rectangle and Circle classes. This way, the Client object can just refer to Shape objects without worrying about what kind of Shape it has been given. As a beginning object-oriented analyst, it might seem natural to implement these