1 / 38

Traditional Design Patterns -- III

Traditional Design Patterns -- III. The material for this lecture was obtained from http://www.dofactory.com/Patterns/Patterns.aspx#list http://www.developer.com/design/article.php/1502691. Adapter Design Pattern.

sade-jordan
Download Presentation

Traditional Design Patterns -- III

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Traditional Design Patterns -- III • The material for this lecture was obtained from • http://www.dofactory.com/Patterns/Patterns.aspx#list • http://www.developer.com/design/article.php/1502691

  2. Adapter Design Pattern • The Adapter is intended to provide a way for a client to use an object whose interface is different from the one expected by the client, without having to modify either • This pattern is suitable for solving issues that arise, for example, when: • 1) you want to replace one class with another and the interfaces do not match, and • 2) you want to create a class that can interact with other classes without knowing their interfaces at design time

  3. Adapter Design Pattern - Operation • First, you create a custom Target class that defines methods using an interface as expected by the client • Second, you create a custom Adapter that implements the interface expected by the Adaptee. The Adapter class subclasses the Target, and provides an alternate implementation of the client requests in terms that the Adaptee expects. Adapter overrides the Target method and provides the correct interface for Adaptee. • This approach has the advantage that it does not lead to modifications in the client. Adapter is a structural pattern and you can use it to react to changes in class interfaces as your system evolves, or you can proactively use the Adapter pattern to build systems that anticipate changing structural details

  4. Adapter Design Pattern

  5. Adapter Design Pattern • Participants: The classes and/or objects participating in this pattern are: • Target • defines the domain-specific interface that Client uses. • Adapter • adapts the interface Adaptee to the Target interface. • Adaptee • defines an existing interface that needs adapting. • Client • collaborates with objects conforming to the Target interface.

  6. Adapter Design Pattern   // "Adaptee"   class Adaptee  {    public void SpecificRequest()    {      Console.WriteLine("Called SpecificRequest()");    }  }} // Client   class MainApp  {    static void Main()    {      // Create adapter and place a request       Target target = new Adapter();      target.Request();      // Wait for user       Console.Read();    }  }   // "Target"   class Target  {    public virtual void Request()    {      Console.WriteLine("Called Target Request()");    }  } class Adapter : Target  {    private Adaptee adaptee = new Adaptee();    public override void Request()    {      // Possibly do some other work       // and then call SpecificRequest       adaptee.SpecificRequest();    }  } Output Called SpecificRequest()

  7. Bridge Design Pattern - Operation • Decouple an abstraction from its implementation so that the two can vary independently • The Bridge pattern is useful when there is a hierarchy of abstractions and a corresponding hierarchy of implementations. Rather than combining the abstractions and implementations into many distinct classes, the Bridge pattern implements the abstractions and implementations as independent classes that can be combined dynamically. Related patterns are : • Layered Architecture The Bridge design pattern is a way of organizing the entities identified using the Layered Architecture pattern into classes. • Abstract Factory The Abstract Factory pattern can be used by the Bridge pattern to decide which implementation class to instantiate for an abstraction object

  8. Bridge Design Pattern • Abstraction • defines the abstraction's interface. • maintains a reference to an object of type Implementor. • RefinedAbstraction • extends the interface defined by Abstraction. • Implementor • defines the interface for implementation classes. This interface doesn't have to correspond exactly to Abstraction's interface; in fact the two interfaces can be quite different. Typically the Implementation interface provides only primitive operations, and Abstraction defines higher-level operations based on these primitives. • ConcreteImplementor • implements the Implementor interface and defines its concrete implementation.

  9. Bridge Design Pattern

  10. Bridge Design Pattern // "Implementor"   abstract class Implementor  {    public abstract void Operation();  }  // "RefinedAbstraction"   class RefinedAbstraction : Abstraction  {    public override void Operation()    {      implementor.Operation();    }  }  // "Abstraction"   class Abstraction  {    protected Implementor implementor;    // Property     public Implementor Implementor    {      set{ implementor = value; }    }    public virtual void Operation()    {      implementor.Operation();    }  }

  11. Bridge Design Pattern // "ConcreteImplementorA"   class ConcreteImplementorA : Implementor  {    public override void Operation()    {      Console.WriteLine("ConcreteImplementorA Operation");    }  }  // "ConcreteImplementorB"   class ConcreteImplementorB : Implementor  {    public override void Operation()    {      Console.WriteLine("ConcreteImplementorB Operation");    }  }

  12. Bridge Design Pattern - Client class MainApp  {    static void Main()    {      Abstraction ab = new RefinedAbstraction();      // Set implementation and call       ab.Implementor = new ConcreteImplementorA();      ab.Operation();      // Change implemention and call       ab.Implementor = new ConcreteImplementorB();      ab.Operation();      // Wait for user       Console.Read();    }  } Output ConcreteImplementorA OperationConcreteImplementorB Operation

  13. State Design Pattern - Operation • Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. • The State pattern is useful when you want to have an object represent the state of an application, and you want to change the state by changing that object. • The State pattern is intended to provide a mechanism to allow an object to alter its behavior in response to internal state changes. To the client, it appears as though the object has changed its class. • The benefit of the State pattern is that state-specific logic is localized in classes that represent that state.

  14. State Design Pattern Participants: The classes and/or objects participating in this pattern are: • Context • defines the interface of interest to clients • maintains an instance of a ConcreteState subclass that defines the current state. • State • defines an interface for encapsulating the behavior associated with a particular state of the Context. • Concrete State • each subclass implements a behavior associated with a state of Context

  15. State Design Pattern

  16. State Design Pattern class Context  {    private State state;    public Context(State Astate)    {      this.state = Astate;    }    // Property     public State State    {      get{ return state; }      set      {         state = value;         Console.WriteLine("State: " + state.GetType().Name);      }    }    public void Request()    {      state.Handle(this);    }  } // "State"   abstract class State  {     public abstract void Handle(Context context);  }  // "ConcreteStateA"   class ConcreteStateA : State  {    public override void Handle(Context context)    {      context.State = new ConcreteStateB();    }  }  // "ConcreteStateB"   class ConcreteStateB : State  {    public override void Handle(Context context)    {      context.State = new ConcreteStateA();    }  }

  17. State Design Pattern - Client static void Main()    {      // Setup context in a state       Context c = new Context(new ConcreteStateA());      // Issue requests, which toggles state       c.Request();      c.Request();      c.Request();      c.Request();      // Wait for user       Console.Read();    }  } Output State: ConcreteStateAState: ConcreteStateBState: ConcreteStateAState: ConcreteStateBState: ConcreteStateA

  18. Factory Method - Operation • When developing classes, you always provide constructors for your clients' use. There are certain circumstances in which you do not want your clients to know which class out of several to instantiate. • The Factory Method is intended to define an interface for clients to use to create an object, but lets subclasses decide which class to instantiate. Factory Methods let a class defer instantiation to subclasses.

  19. Factory Method • The classes and/or objects participating in this pattern are: • Product • defines the interface of objects the factory method creates • ConcreteProduct • implements the Product interface • Creator • declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object. • may call the factory method to create a Product object. • ConcreteCreator • overrides the factory method to return an instance of a ConcreteProduct.

  20. Factory Method

  21. Factory Method // "ConcreteCreator"   class ConcreteCreatorA : Creator  {    public override Product FactoryMethod()    {      return new ConcreteProductA();    }  }  // "ConcreteCreator"   class ConcreteCreatorB : Creator  {    public override Product FactoryMethod()    {      return new ConcreteProductB();    }  }}   abstract class Product  {  }  // "ConcreteProductA"   class ConcreteProductA : Product  {  }  // "ConcreteProductB"   class ConcreteProductB : Product  {  }  // "Creator"   abstract class Creator  {    public abstract Product FactoryMethod();  }

  22. Factory Method - Client   class MainApp  {    static void Main()    {      // An array of creators       Creator[] creators = new Creator[2];      creators[0] = new ConcreteCreatorA();      creators[1] = new ConcreteCreatorB();      // Iterate over creators and create products       foreach(Creator creator in creators)      {         Product product = creator.FactoryMethod();         Console.WriteLine("Created {0}",           product.GetType().Name);      }      // Wait for user        Console.Read();    }  } Output: Created ConcreteProductACreated ConcreteProductB

  23. Command Design Pattern - Operation • The Command pattern is intended to encapsulate a request as an object. For example, consider a window application that needs to make requests of objects responsible for the user interface. • The client responds to input from the user by creating a command object and the receiver. It then passes this object to an Invoker object, which then takes the appropriate action. This allows the client to make requests without having to know anything about what action will take place. • In addition, you can change that action without affecting the client. Practical uses for Command are for creating queues and stacks for supporting "undo" operations, configuration changes, and so on.

  24. Command Design Pattern Participants: The classes and/or objects participating in this pattern are: • Command(e.g. Command) • declares an interface for executing an operation • ConcreteCommand(e.g. CalculatorCommand) • defines a binding between a Receiver object and an action • implements Execute by invoking the corresponding operation(s) on Receiver • Client(e.g. CommandApp) • creates a ConcreteCommand object and sets its receiver • Invoker(e.g. User) • asks the command to carry out the request • Receiver(e.g. Calculator) • knows how to perform the operations associated with carrying out the request

  25. Command Design Pattern

  26. Command Design Pattern // "Receiver" class Receiver   {    public void Action()    {      Console.WriteLine("Called Receiver.Action()");    }  }  // "Invoker"   class Invoker   {    private Command command;    public void SetCommand(Command command)    {      this.command = command;    }    public void ExecuteCommand()    {      command.Execute();    }      } abstract class Command   {    protected Receiver receiver;    // Constructor     public Command(Receiver receiver)    {      this.receiver = receiver;    }    public abstract void Execute();  }  // "ConcreteCommand"   class ConcreteCommand : Command  {    // Constructor     public ConcreteCommand(Receiver receiver) :       base(receiver)     {      }    public override void Execute()    {      receiver.Action();    }  }

  27. Command Design Pattern - Client   class MainApp  {    static void Main()    {      // Create receiver, command, and invoker       Receiver receiver = new Receiver();      Command command = new ConcreteCommand(receiver);      Invoker invoker = new Invoker();      // Set and execute command       invoker.SetCommand(command);      invoker.ExecuteCommand();      // Wait for user       Console.Read();    }  } Output Called Receiver.Action()

  28. Proxy Design Pattern - Operation • Provide a surrogate or placeholder for another object to control access to it. • This pattern is useful for situations where object creation is a time consuming process and can make an application appear sluggish. A proxy object can provide the client with feedback while the object is being created. • Proxy can also be used to provide a more sophisticated reference to an object. For example, the proxy object can implement additional logic on the objects behalf (security, remote procedure calls, an so forth).

  29. Proxy Design Pattern Participants: The classes and/or objects participating in this pattern are: • Proxy (MathProxy) • maintains a reference that lets the proxy access the real subject. Proxy may refer to a Subject if the RealSubject and Subject interfaces are the same. • provides an interface identical to Subject's so that a proxy can be substituted for for the real subject. • controls access to the real subject and may be responsible for creating and deleting it. • other responsibilites depend on the kind of proxy: • remote proxies are responsible for encoding a request and its arguments and for sending the encoded request to the real subject in a different address space. • virtual proxies may cache additional information about the real subject so that they can postpone accessing it. For example, the ImageProxy from the Motivation caches the real images's extent. • protection proxies check that the caller has the access permissions required to perform a request. • Subject (IMath) • defines the common interface for RealSubject and Proxy so that a Proxy can be used anywhere a RealSubject is expected. • RealSubject (Math) • defines the real object that the proxy represents

  30. Proxy Design Pattern

  31. Proxy Design Pattern   // "Proxy"   class Proxy : Subject  {    RealSubject realSubject;    public override void Request()    {      // Use 'lazy initialization'       if (realSubject == null)      {        realSubject = new RealSubject();      }      realSubject.Request();    }    } // "Subject"   abstract class Subject   {    public abstract void Request();      }  // "RealSubject"   class RealSubject : Subject  {    public override void Request()    {      Console.WriteLine("Called RealSubject.Request()");    }  }

  32. Proxy Design Pattern - Client   class MainApp  {    static void Main()    {      // Create proxy and request a service       Proxy proxy = new Proxy();      proxy.Request();      // Wait for user       Console.Read();    }  } Output Called RealSubject.Request()

  33. Chain of Responsibility Design Pattern • One of the tenets of software engineering is to keep objects loosely coupled. The Chain of Responsibility is intended to promote loose coupling between the sender of a request and its receiver by giving more than one object an opportunity to handle the request. • The receiving objects are chained and pass the request along the chain until one of the objects handles it. • The result is to avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

  34. Chain of Responsibility Design Pattern • Participants: The classes and/or objects participating in this pattern are: • Handler • defines an interface for handling the requests • (optional) implements the successor link • ConcreteHandler • handles requests it is responsible for • can access its successor • if the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor • Client • initiates the request to a ConcreteHandler object on the chain

  35. Chain of Responsibility Design Pattern

  36. Chain of Responsibility Design Pattern // "Handler" abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) {   this.successor = successor; }  public abstract void HandleRequest(int request); } // "ConcreteHandler1"   class ConcreteHandler1 : Handler  {    public override void HandleRequest(int request)    {      if (request >= 0 && request < 10)      {        Console.WriteLine("{0} handled request {1}",           this.GetType().Name, request);      }      else if (successor != null)      {        successor.HandleRequest(request);      }    }  }

  37. Chain of Responsibility Design Pattern // "ConcreteHandler3"   class ConcreteHandler3 : Handler  {    public override void HandleRequest(int request)    {      if (request >= 20 && request < 30)      {        Console.WriteLine("{0} handled request {1}",           this.GetType().Name, request);      }      else if (successor != null)      {        successor.HandleRequest(request);      }    }  } // "ConcreteHandler2"   class ConcreteHandler2 : Handler  {    public override void HandleRequest(int request)    {      if (request >= 10 && request < 20)      {        Console.WriteLine("{0} handled request {1}",           this.GetType().Name, request);      }      else if (successor != null)      {        successor.HandleRequest(request);      }    }  }

  38. Chain of Responsibility Design Pattern class MainApp  {    static void Main()    {      // Setup Chain of Responsibility       Handler h1 = new ConcreteHandler1();      Handler h2 = new ConcreteHandler2();      Handler h3 = new ConcreteHandler3();      h1.SetSuccessor(h2);      h2.SetSuccessor(h3);      // Generate and process request       int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};      foreach (int request in requests)      {        h1.HandleRequest(request);      }      // Wait for user       Console.Read();    }  } Output ConcreteHandler1 handled request 2ConcreteHandler1 handled request 5ConcreteHandler2 handled request 14ConcreteHandler3 handled request 22ConcreteHandler2 handled request 18ConcreteHandler1 handled request 3ConcreteHandler3 handled request 27ConcreteHandler3 handled request 20

More Related