Friday 2 May 2014


Software Design Patterns                               Dhanush P
                                                                       1MS10IS033
Design Patterns?

  • Design patterns are a "solution to a problem in a context". 
  • It can also be defined as "a proven solution to a recurring problem". 

Software architects develop patterns inorder to solve software problems that are encountered by them. they exactly know which pattern to use by carefully studying the requirements of the problem and the existing situation. This knowledge is gained to individuals by time and practice.

Why do require design patterns?

There may be many reasons and requirements to use patterns. a few of them are

  • Design patterns help in designing models more quickly because the patterns predicte for software architects what ought to be there. They tell what the essential objects are and what to pay special attention to.
  • Using patterns developer can communicate much more effectively with experts because they would have a more structured way to deal with the details and exceptions.
  • Τhe patterns allows to develop better end-user training for the system under development because the patterns predicted the most important features of the system.
  • Reuse solutions—By reusing already established designs, we get a head start on my problems and avoid gotchas. We get the benefit of learning from the experience of others. We do not have to reinvent solutions for commonly recurring problems.
  • Establish common terminology—Communication and teamwork require a common base of vocabulary and a common viewpoint of the problem. Design patterns provide a common point of reference during the analysis and design phase of a project.
Key features of a pattern

The following key features are required to describe a pattern


Item

Description

NameAll patterns have a unique name that identifies them
IntentThe purpose of the pattern
ProblemThe problem that the pattern is trying to solve
SolutionHow the pattern provides a solution to the problem in the context in which it shows up
Participants and CollaboratorsThe entities involved in the pattern
ConsequencesThe consequences of using the pattern. Investigates the forces at play in the pattern
ImplementationHow the pattern can be implemented
Although there are many design patterns we discuss only the basic and the frequently used patterns known as the "Gang of Four" patterns. They have been explained below along with examples.

The Facade Pattern

Intent
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
Basically, this is saying that we need a new way to interact with a system that is easier than the current way, or we need to use the system in a particular way



                                                 Standard, simplified view of the Facade pattern.

Key features

IntentYou want to simplify how to use an existing system. You need to define your own interface.
ProblemYou need to use only a subset of a complex system. Or you need to interact with the system in a particular way
SolutionThe Facade presents a new interface for the client of the existing system to use
Participants and CollaboratorsIt presents a specialized interface to the client that makes it easier to use
ConsequencesThe Facade simplifies the use of the required subsystem. However, since the Facade is not complete, certain functionality may be unavailable to the client
Implementation• Define a new class (or classes) that has the required interface.
• Have this new class use the existing system
C++ sample code implementing the facade pattern  

class A {
    private B b; // Class A uses Class B, the "interface"
    public int f() { return b.g(); }
};

class B {
    private C c; // class B uses class C, a "subsystem"
    private ... ...; // other subsystems can be added
    public int g() { c.h(); return c.i(); }
};

class C { // a subsystem
    public void h() { ... }
    public int i() { return x; }
};


The Adapter Pattern

Intent
Convert the interface of a class into another interface that the clients expect. Adapter lets classes work together that could not otherwise because of incompatible interfaces.
Basically, this is saying that we need a way to create a new interface for an object that does the right stuff but has the wrong interface.

Key Features

Intent    Match an existing object beyond your control to a particular interface
Problem    A system has the right data and behavior but the wrong interface. Typically
    used when you have to make something a derivative of an abstract
    class we are defining or already have.
Solution    The Adapter provides a wrapper with the desired interface
Participants and
Collaborators
    The Adapter adapts the interface of an Adaptee to mat ch that of the
    Adapter's Target (the class it derives from). This allows the Client
    to use the Adaptee as if it were a type of Target.
Consequences    The Adapter pattern allows for preexisting objects to fit into new class
    structures without being limited by their interfaces.
Implementation    Contain the existing class in another class. Have the containing class
    match the required interface and call the methods of the contained class.

Standard and simplified view of adapter pattern

C++ code implementing the adapter pattern    

#include <iostream.h> typedef int Coordinate; typedef int Dimension; // Desired interface class Rectangle {   public:     virtual void draw() = 0; }; // Legacy component class LegacyRectangle {   public:     LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2)     {         x1_ = x1;         y1_ = y1;         x2_ = x2;         y2_ = y2;         cout << "LegacyRectangle:  create.  (" << x1_ << "," << y1_ << ") => ("           << x2_ << "," << y2_ << ")" << endl;     }     void oldDraw()     {         cout << "LegacyRectangle:  oldDraw.  (" << x1_ << "," << y1_ <<           ") => (" << x2_ << "," << y2_ << ")" << endl;     }   private:     Coordinate x1_;     Coordinate y1_;     Coordinate x2_;     Coordinate y2_; }; // Adapter wrapper 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 <&lt;           "), width = " &lt;&lt; w &lt;&lt; ", height = " &lt;&lt; h &lt;&lt; endl;     }     virtual void draw()     {         cout &lt;&lt; "RectangleAdapter: draw." &lt;&lt; endl;         oldDraw();     } }; int main() {   Rectangle *r = new RectangleAdapter(120, 200, 60, 40);   r->draw(); }

The Bridge Pattern

Intent
According to the gang of four the intent of bridge pattern is to “De-couple an abstraction from its implementation so that the two can vary independently".
  • De-couple means to have things behave independently from each other or at least explicitly state what the relationship is, and
  • Abstraction is how different things are related to each other conceptually. 
Key Features

Intent   Decouple a set of implementations from the set of objects using them.
Problem   The derivations of an abstract class must use multiple implementations
   without causing an explosion in the number of classes.
Solution   Define an interface for all implementations to use and have the derivations
   of the abstract class use that.
Participants and
Collaborators
   The Abstraction defines the interface for the objects being
   implemented. The Implementor defines the interface for the specific
   implementation classes. Classes derived from the Abstraction use
   classes derived from the Implementor without knowing which particular
   Concrete Implementor is in use.
Consequences   The decoupling of the implementations from the objects that use them
   increases extensibility. Client objects are not aware of implementation
   issues.
Implementation   • Encapsulate the implementations in an abstract class.
   • Contain a handle to it in the base class of the abstraction being implemented.
Standard and simplifies view of bridge pattern

C++ code implementing the bridge pattern   

class Program
    {
        static void Main(string[] args)
        {
            IAppliance tv = new TV("Bedroom TV");  //implementation object
            IAppliance vacuum = new VaccumCleaner
("My Vacuum Cleaner");  //implementation object

            Switch s1 = GetSwitch(tv);  //convert to abstraction
            Switch s2 = GetSwitch(vaccum);  //convert to abstraction

            //*** client code works only with the abstraction objects, 
  //not the implementation objects ***
            s1.TurnOn();
            s2.TurnOn();
        }

        //convert implementation object to abstraction object
        static Switch GetSwitch(IAppliance a)
        {
            return new RemoteControl(a);
        }
    }

    //the abstraction
    public abstract class Switch
    {
        protected IAppliance appliance;
        public abstract void TurnOn();
    }

    //the implementation
    public interface IAppliance
    {
        void Run();
    }

    //concrete abstraction
    public class RemoteControl : Switch
    {
        public RemoteControl(IAppliance i)
        {
            this.appliance = i;
        }

        public override void TurnOn()
        {
            appliance.Run();
        }
    }

    //concrete implementation
    public class TV : IAppliance
    {
        private string name;

        public TV(string name)
        {
            this.name = name;
        }

        void IAppliance.Run()
        {
            Console.WriteLine(this.name + " is running");
        }
    }

    //concrete implementation
    public class VaccumCleaner : IAppliance
    {
        private string name;

        public VaccumCleaner(string name)
        {
            this.name = name;
        }void IAppliance.Run()
        {
            Console.WriteLine(this.name + " is running");
        }
    }


The Abstract Factory Pattern

Intent
To to provide an interface for creating families of related or dependent objects without specifying their concrete classes.
Sometimes, several objects need to be instantiated in a coordinated fashion. For example, when dealing with user interfaces, the system might need to use one set of objects to work on one operating system and another set of objects to work on a different operating system. The Abstract Factory pattern ensures that the system always gets the correct objects for the situation.

Key Features

Intent   You want to have families or sets of objects for particular clients.
Problem   Families of related objects need to be instantiated.
Solution   Coordinates the creation of families of objects. Gives a way to take the
   rules of how to perform the instantiation out of the client object that is
   using these created objects..
Participants and
Collaborators
   The AbstractFactory defines the interface for how to create each
   member of the family of objects required. Typically, each family is created
   by having its own unique ConcreteFactory.
Consequences   The pattern isolates the rules of which objects to use from the logic of
   how to use these objects.
Implementation   Define an abstract class that specifies which objects are to be made.
   Then implement one concrete class for each family. Tables or fi les can
   also be used to accomplish the same thing.


Standard and simplified view of Abstract factory pattern

 C++ code implementing the Abstract factory pattern   

#include <iostream>
#include <string>
using namespace std;
// Abstract base class
class Mobile {
    public:
       virtual string Camera() = 0;
       virtual string KeyBoard() = 0;
       void PrintSpecs() {
          cout << Camera() << endl;
          cout << KeyBoard() << endl;
       }
};
// Concrete classes
class LowEndMobile : public Mobile {
    public:
       string Camera() {
          return "2 MegaPixel";
       }
       string KeyBoard() {
          return "ITU-T";
       }
};
// Concrete classes
class HighEndMobile : public Mobile {
    public:
       string Camera() {
          return "5 MegaPixel";
       }
       string KeyBoard() {
          return "Qwerty";
       }
};
// Abstract Factory returning a mobile
class MobileFactory {
    public:
       Mobile* GetMobile(string type);
};
Mobile* MobileFactory::GetMobile(string type) {
    if ( type == "Low-End" ) return new LowEndMobile();
    if ( type == "High-End" ) return new HighEndMobile();
    return NULL;
}
void main()
{
   MobileFactory* myFactory = new MobileFactory();
   Mobile* myMobile1 = myFactory->GetMobile("Low-End");
   myMobile1->PrintSpecs();
   Mobile* myMobile2 = myFactory->GetMobile("High-End");
   myMobile2->PrintSpecs();
}


The Strategy Pattern

Intent
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

The Strategy pattern is based on a few principles:
  • Objects have responsibilities.
  • Different, specific implementations of these responsibilities are manifested through the use of polymorphism.
  • There is a need to manage several different implementations of what is, conceptually, the same algorithm.
  • It is a good design practice to separate behaviors that occur in the problem domain from each other— that is, to decouple them. This allows me to change the class responsible for one behavior without adversely affecting another.

Key Features

Intent   Allows you to use different business rules or algorithms depending upon the
   context in which they occur.
Problem   The selection of an algorithm that needs to be applied depends upon the
   client making the request or the data being acted upon. If you simply have a
   rule in place that does not change, you do not need a Strategy pattern..
Solution   Separates the selection of algorithm from the implementation of the algorithm.
   Allows for the selection to be made based upon context.
Participants and
Collaborators
   •   The strategy specifies how the different algorithms are used.
       Collaborators
   •   The concreteStrategies implement these different algorithms.
   •   The Context uses the specific ConcreteStrategy with a reference of
       type Strategy. The strategy and Context interact to implement the
       chosen algorithm (sometimes the strategy must query the Context).
       The Context forwards requests from its Client to the Strategy.
Consequences   •   The Strategy pattern defines a family of algorithms.
   •   Switches and/or conditionals can be eliminated.
   •   You must invoke all algorithms in the same way (they must all have the
        same interface). The interaction between the ConcreteStrategies
        and the Context may require the addition of getstate type methods
        to the Context.
Implementation   Have the class that uses the algorithm (the Context) contain an abstract
   class (the stragegy) that has an abstract method specifying how to call the
   algorithm. Each derived class implements the algorithm as needed. Note:
   this method wouldn't be abstract if you wanted to have some default behavior.


Standard and simplified structure of strategy pattern

C++ code implementing strategy pattern

class Interface {  //this class and all sorting clases could be templated to be able to deal with sorting lists of different data types
    std::unique_ptr<ISort> sorter_;
public:
    Interface():sorter_(new CQuickSorter()){ //CQuickSorter is the default sorter
    }
    template<typename T>
    setSorter(){    //one could also use perfect forwarding to pass arguments to T's constructor
        sorter_.reset(new T());
    }
    void sort(std::list<string> &list){
        sorter_->sort(list);
    }
};

int main(){
    std::list<int> li;
    Interface cn;
    cn.sort(li);  //using a default sort
    cn.setSorter<CBubbleSort>();
    cn.sort(li);  //using bubble sort
}


Decorator Pattern

Intent
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
The Decorator pattern works by allowing me to create a chain of objects that starts with the decorator objects— the objects responsible for the new function— and ends with the original object.

Key Features

Intent   Attach additional responsibilities to an object dynamically.
Problem   The object that you want to use does the basic functions you require.
   However, you may need to add some additional functionality to the object,
   occurring before or after the object's base functionality. Note that the Java
   foundation classes use the Decorator pattern extensively for I/O handling.
Solution   Allows for extending the functionality of an object without resorting to subclassing.
Participants and
Collaborators
   The ConcreteComponent is the class having function added to it by the
   Decorators. Sometimes classes derived from ConcreteComponent
   are used to provide the core functionality, in which case
   Concrete-Component is no longer concrete, but rather abstract. The
   Component defines the interface for all of these classes to use..
Consequences   Functionality that is to be added resides in small objects. The advantage is
   the ability to dynamically add this function before or after the functionality in
   the ConcreteComponent. Note: While a decorator may add its
   functionality before or after that which it decorates, the chain of instantiation
   always ends with the ConcreteComponent.
Implementation   Create an abstract class that represents both the original class and the new
   functions to be added to the class. In the decorators, place the new function
   calls before or after the trailing calls to get the correct order.

Standard and simplified view of decorator pattern

Java code implementing decorator pattern

class SalesTicket extends Component
{ public void prtTicket () {
// sales ticket printing code here
}
abstract class Decorator extends Component
{ private Component myComp; public Decorator
(Component myC) { myComp= myC;
}
public void prtTicket () { if
(myComp != null)
myComp.prtTicket(); }
}
class Headerl extends Decorator
{ public void prtTicket () {
// place printing header 1 code here
super.prtTicket(); } }
class Header2 extends Decorator
{ public void prtTicket () {
// place printing header 2 code here
super.prtTicket(); } }
class Footerl extends Decorator
{ public void prtReport ()
{ super.prtTicket();
// place printing footer 1 code here } }
class Footer2 extends Decorator
{ public void prtReport ()
{ super.prtTicket();
// place printing footer 2 code here } }
class SalesOrder { void
prtTicket () {
Component myST;
// Get chain of Decorators and SalesTicket built by
// another object that knows the rules to use.
// This may be done in constructor instead of
// each time this is called.
myST= Configuration.getSalesTicket()
// Print Ticket with headers and footers as needed
myST.prtTicket 0 ; } }


The Singleton Pattern

Intent
Ensure a class only has one instance, and provide a global point of access to it.

The Singleton pattern works by having a special method that is used to instantiate the desired object. When this method is called, it checks to see if the object has already been instantiated. If it has, the method simply returns a reference to the object. If not, the method instantiates it and returns a reference to the new instance.
To ensure that this is the only way to instantiate an object of this type, I define the constructor of this class to be protected or private.

Standard and simplified structure of singleton pattern

Key Features

Intent   You want to have only one of an object but there is no global object that controls
   the instantiation of this object.
Problem   Several different client objects need to refer to the same thing and you want
   to ensure that you do not have more than one of them.
Solution   Guarantees one instance.
Participants and
Collaborators
   Clients create an get Instance of the Singleton solely through the
    instance method.
Consequences   Clients need not concern themselves whether an instance of the
   Singleton exists. This can be controlled from within the Singleton..
Implementation   • Add a private static member of the class that refers to the desired object
      (initially, it is NULL).
   • Add a public static method that instantiates this class if this member is
      NULL (and sets this member's value) and then returns the value of this
      member.
   • Set the constructor's status to protected or private so that no one can
      directly instantiate this class and bypass the static constructor mechanism.

C++ code implementing singleton pattern

Class USTax
{ public:
static USTax* getlnstance();
private:
USTax(};
static USTax* instance;
}
USTax::USTax ()
{ instance= 0;
}
USTax* USTax::getlnstance () { if
(instance== 0) {
instance= new USTax;
} return
instance;
}

The Observer Pattern

Intent
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Standard and simplified structure of observer pattern

Key Features

Intent   Define a one-to-many dependency between objects so that when one
   object changes state, all its dependents are notified and updated automatically.
Problem   You need to notify a varying list of objects that an event has occurred.
Solution   Observers delegate the responsibility for monitoring for an event to a central
   object: the Subject.
Participants and
Collaborators
   The Subject knows its Observers because the Observers register
   with it. The Subject must notify the Observers when the event in question
   occurs. The Observers are responsible both for registering with the
   Subject and for getting the information from the Subject when notified.
Consequences   Subjects may tell Observers about events they do not need to know if
   some Observers are interested in only a subset of events. Extra communication
   may be required if Subjects notify Observers which then go back and
   request additional information.
Implementation   • Have objects (Observers) that want to know when an event happens
     attach themselves to another object (Sub j ect) that is watching for the
     event to occur or that triggers the event itself.
   • When the event occurs, the Subject tells the Observers that it has
      occurred.
   • The Adapter pattern is sometimes needed to be able to implement the
      Observer interface for all of the Observer-type objects.

C++ code implementing observer pattern 

//observer.h
#ifndef OBSERVER_H_INCLUDED
#define OBSERVER_H_INCLUDED
#include <string>
class Publisher;
class Observer {
public:
    virtual void eventOnProperty(Publisher* source,
         std::string event_name, std::string value) = 0;
};

//publisher.h
#ifndef PUBLISHER_H_INCLUDED
#define PUBLISHER_H_INCLUDED
#include "Observer.h"
#include <list>
#include <string>
class Publisher {
public:
    void notify_observers(std::string, std::string);
    void add_observer(Observer*);
protected:
    std::list<Observer*> my_observers;
};

publisher.cpp

#include "Publisher.h"
#include "Observer.h"
#include <string>
#include <list>
void Publisher::notify_observers(std::string event_name, std::string value) {
    std::list<Observer*>::iterator it;
    for(it = my_observers.begin(); it != my_observers.end(); it++) {
        (*it)->eventOnProperty(this, event_name, value);
    }
}
void Publisher::add_observer(Observer* obs) {
    my_observers.push_back(obs);
}


The Template Method Pattern

Intent
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Redefine the steps in
an algorithm without changing the algorithm's structure.
In other words, although there are different methods for connecting and querying Oracle databases and SQL Server databases, they share the same conceptual process. The Template Method gives us a way to capture this common ground in an abstract class while encapsulating the differences in derived classes. The Template
Method pattern is about controlling a sequence common to different processes.

Standard and simplified structured view of  template method pattern

Key Features

Intent   Define the skeleton of an algorithm in an operation, deferring some steps
   to subclasses. Redefine the steps in an algorithm without changing the
   algorithm's structure.
Problem   There is a procedure or set of steps to follow that is consistent at one
   level of detail, but individual steps may have different implementations at
   a lower level of detail.
Solution   Allows for definition of substeps that vary while maintaining a consistent
   basic process..
Participants and
Collaborators
   The Template Method consists of an abstract class that defines the basic
   TemplateMethod (see figure below) classes that need to be overridden.
   Each concrete class derived from the abstract class implements a
   new method for the Template.
Consequences   Templates provide a good platform for code reuse. They also are helpful
   in ensuring the required steps are implemented. They bind the overridden
   steps together for each Concrete class, and so should only be
   used when these variations always and only occur together.
Implementation   Create an abstract class that implements a procedure using abstract
   methods. These abstract methods must be implemented in subclasses to
   perform each step of the procedure. If the steps vary independently, each
   step may be implemented with a Strategy pattern.

C++ code implementing the template method pattern

#include <iostream> using namespace std; class Base {     void a()     {         cout << "a  ";     }     void c()     {         cout << "c  ";     }     void e()     {         cout << "e  ";     }     // 2. Steps requiring peculiar implementations are "placeholders" in base class     virtual void ph1() = 0;     virtual void ph2() = 0;   public:     // 1. Standardize the skeleton of an algorithm in a base class "template method"     void execute()     {         a();         ph1();         c();         ph2();         e();     } }; class One: public Base {     // 3. Derived classes implement placeholder methods      /*virtual*/void ph1()     {         cout << "b  ";     }      /*virtual*/void ph2()     {         cout << "d  ";     } }; class Two: public Base {      /*virtual*/void ph1()     {         cout << "2  ";     }      /*virtual*/void ph2()     {         cout << "4  ";     } }; int main() {   Base *array[] =   {      &One(), &Two()   };   for (int i = 0; i < 2; i++)   {     array[i]->execute();     cout << '\n';   } }


The Factory Method  Pattern

Intent
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Standard and simplifies view of factory method pattern

Key Features

Intent   Define an interface for creating an object, but let subclasses decide
   which class to instantiate. Defer instantiation to subclasses.
Problem   A class needs to instantiate a derivation of another class, but doesn't
   know which one. Factory Method allows a derived class to make this
   decision.
Solution   A derived class makes the decision on which class to instantiate and
   how to instantiate it.
Participants and
Collaborators
   Product is the interface for the type of object that the Factory Method
   creates. Creator is the interface that defines the Factory Method.
Consequences   Clients will need to subclass the Creator class to make a particular
   ConcreteProduct.
Implementation   Use a method in the abstract class that is abstract (pure virtual in
   C++). The abstract class' code refers to this method when it needs to
   instantiate a contained object but does not know which particular
   object it needs.

C++ code implementing the factory method pattern

#include <iostream>
#include <string>
using namespace std;
// Abstract base class
class Mobile {
    public:
       virtual string Camera() = 0;
       virtual string KeyBoard() = 0;
       void PrintSpecs() {
          cout << Camera() << endl;
          cout << KeyBoard() << endl;
       }
};
// Concrete classes
class LowEndMobile : public Mobile {
    public:
       string Camera() {
          return "2 MegaPixel";
       }
       string KeyBoard() {
          return "ITU-T";
       }
};
// Concrete classes
class HighEndMobile : public Mobile {
    public:
       string Camera() {
          return "5 MegaPixel";
       }
       string KeyBoard() {
          return "Qwerty";
       }
};
// Abstract Factory returning a mobile
class MobileFactory {
    public:
       Mobile* GetMobile(string type);
};
Mobile* MobileFactory::GetMobile(string type) {
    if ( type == "Low-End" ) return new LowEndMobile();
    if ( type == "High-End" ) return new HighEndMobile();
    return NULL;
}
void main()
{
   MobileFactory* myFactory = new MobileFactory();
   Mobile* myMobile1 = myFactory->GetMobile("Low-End");
   myMobile1->PrintSpecs();
   Mobile* myMobile2 = myFactory->GetMobile("High-End");
   myMobile2->PrintSpecs();
}

                                                                                                                       

Labels: