View
217
Download
2
Tags:
Embed Size (px)
Citation preview
Design Patterns Examplesin C++
Moshe FreskoBar-Ilan University
Object Oriented Programming 2006-2007
Design Patterns Design Patterns help you learn from
others’ successes, instead of your failures Separate things that change, from the
things that doesn’t change Elegant and Cheap-to-Maintain Three classes of DPs
1. Creational2. Behavioral3. Structural
Creational Design Patterns Creational DP:
Abstracts the instantiation process. Help make a system independent of how
objects are created, composed, represented. Two types
1. Class creationalUses inheritance to vary the class to be instantiated
2. Object creationalDelegates instantiation to another object
Structural Patterns
Structural Patterns are concerned with how classes and objects are composed to form larger structures.
Examples: Adapter: Makes an interface to conform to another. So it
makes a uniform abstraction of different interfaces. Composite: Describes how to build class hierarchy made up
of classes for two kinds of objects: primitive and composite. Decorator: How to add responsibilities to objects dynamically. Proxy Flyweight
Behavioral Patterns Behavioral Patterns are concerned with algorithms and the
assignment of responsibilities between objects. Not only patterns of objects/classes but also patterns of
communication between them. These patterns are:
Template Method: An abstract definition of an algorithm. Interpreter: Represents a grammar as a class hierarchy and
implements an interpreter as an operation on instances of these classes.
Mediator: Provides the indirection needed for loose coupling. Observer: Defines and Maintains dependency between objects.
(MVC) Strategy: Encapsulates an algorithm in an Object. Command: Encapsulates a request in an Object. Iterator: Abstracts the way you access and traverse objects in
an aggregate.
Creational Patterns
Creational Patterns are important as systems depend more on object composition
Creational Patterns Encapsulate concrete classes system
uses Hide how instances of these classes
are created
Example: To build a Maze
Maze example
enum Direction { North, South, East, West } ;
class MapSite { public: void Enter() = 0 ; } ;
class Room: public MapSite { public: Room(int roomNo) ; { roomNumber = number ; } MapSite* GetSide(Direction d) { return sides[d] ; } void SetSide(Direction d, MapSite* m) { sides[d] = m ; } void Enter() { /* … do something … */ } private: MapSite* sides[4] ; int roomNumber ; } ;
class Wall: public MapSite {
public:
Wall() ;
virtual void Enter() ;
} ;
class Door: public MapSite {
public:
Door(Room*=0, Room*=0) ;
virtual void Enter() ;
Room* OtherSideFrom(Room*);
private:
Room* room1 ;
Room* room2 ;
bool isOpen;
} ;
Maze Exampleclass Maze {public: Maze() ;
void addRoom(Room r) ; Room* RoomNo(int) const;private: // …};
Maze Example
class MazeGame{ public: Maze* CreateMaze() { Maze* maze = new Maze() ; Room* room1 = new Room(1) ; Room* room2 = new Room(2) ; Door* door = new Door(room1,room2) ;
maze->AddRoom(room1) ; maze->AddRoom(room2) ;
room1->SetSide(North, new Wall()) ; room1->SetSide(East , door) ; room1->SetSide(South, new Wall()) ; room1->SetSide(West , new Wall()) ;
room2->SetSide(North, new Wall()) ; room2->SetSide(East , new Wall()) ; room2->SetSide(South, new Wall()) ; room2->SetSide(West , door) ;
return maze ;}
}
Factory Method Intent: Define an interface for creating
an object, but let subclasses decide which cass to instantiate.
Motivation: Example: Framework of Abstract classes
Abstract classes: Document, Application Application has Open, New, etc. to create new
documents Application cannot know which concrete document
to instant Concrete classes: DrawingDocument,
DrawingApplication
Factory Method Solution
CreateDocument() = Factory Method
Factory Method
Applicability: Use the Factory Method when
A class can’t anticipate the class of objects it must create
A class wants its subclasses to specify the objects it creates
Factory Method
Factory Method - Participants
Product (Document) The interface of objects the Factory Method
creates ConcreteProduct (MyDocument)
Implements the product interface Creator (Application)
Declares the factory method which returns an object of type Product
ConcreteCreator (MyApplication) Defines the Factory method to returnn an
instance of ConcreteProduct
Factory Method Implementation
Abstract Creator Class v.s. Concrete Creator Class
Parameterized Factory Method Creator can keep the Class Info to
instantiate (Can avoid sub classing)
To use naming conventions
Factory Methods in Maze Example
class MazeGame{public:
virtual Maze* MakeMaze() const{ return new Maze() ; }
virtual Room* MakeRoom(int n){ return new Room(n) ; }
virtual Wall* MakeWall(){ return new Wall() ; }
virtual Door* MakeDoor(Room* r1, Room* r2){ return new Door(r1,r2) ; }
Maze* CreateMaze() {Maze* maze = MakeMaze() ;Room* room1 = MakeRoom(1) ;Room* room2 = MakeRoom(2) ;Door* door = MakeDoor(room1,room2) ;………………………return maze ;
}} ;
Customized Maze Componentsclass BombedWall: public Wall {
// …} ;
class RoomWithABomb: public Room {public:
RoomWithABomb(int n) : Room(n) { }} ;
class BombedMazeGame: public MazeGame {public:
BombedMazeGame();virtual Wall* MakeWall()
{ return new BombedWall() ; }virtual Room* MakeRoom(int n)
{ return new RoomWithABomb(n) ; }} ;
Abstract Factory Intent: Provides an interface for creating
families of related or dependent objects without specifying their concrete classes.
Motivation: User interface Toolkit supporting multiple
look-and- feel standards. (Widgets like Scroll Bars, Windows, Buttons etc.)
Not to hard code these widgets for a particular look-and-feel otherwise hard to change it
We can define a WidgetFactory interface for creating each basic entity
Abstract Factory Example
Abstract Factory - Applicability
Use Abstract Factory if A system must be independent of how its
products are created A system should be configured with one of
multiple families of products A family of related objects must be used
together You want to reveal only interfaces of a
family of products and not their implementations
Abstract Factory - Structure
Abstract Factory - Participants
AbstractFactory (WidgetFactory) Declares an interface of methods to create abstract product
objects ConcreteFactory (MotifWidgetFactory,…)
Implements the methods to create concrete product objects AbstractProduct (Window, ScrollBar)
Declares an interface for a product type ConcreteProduct (MotifWindow, MotifScrollBar)
Defines a product object Implements the AbstractProduct interface
Client Uses only interfaces declared by AbstractFactory and
AbstractProduct
Abstract Factory - Implementation
Factory better to be a Singleton A new Concrete Factory for each
Platform.Or alternatively a single Concrete Factory keeping its Classes of Products.
Extending the Factories. (Adding a new Product)
Abstract Factory – Maze Example
class MazeFactory {public:
Maze* MakeMaze(){ return new Maze() ; }
Room* MakeRoom(int n){ return new Room(n) ; }
Wall* MakeWall(){ return new Wall() ; }
Door* MakeDoor(Room r1, Room r2){ return new Door(r1,r2) ; }
} ;
class MazeGame {public:
Maze* CreateMaze(MazeFactory* factory) {Maze* maze = factory->newMaze() ;Room* room1 = factory->newRoom(1) ;Room* room2 = factory->newRoom(2) ;Door* door = factory->newDoor(room1,room2) ;………………………return maze ;
}}
Customizing Maze Factoryclass BombedWall: public Wall {
// …} ;
class RoomWithABomb: public Room {public:
RoomWithABomb(int n) : Room(n) { }} ;
class BombedMazeFactory: public MazeFactory {public:
BombedMazeGame();virtual Wall* MakeWall()
{ return new BombedWall() ; }virtual Room* MakeRoom(int n)
{ return new RoomWithABomb(n) ; }} ;
Singleton Intent: Ensure that a class has only one
instance, and provide a global point of access to it.
Use Singleton There must be exactly one instance of a
class, and it must be accessible to clients from a well known access point.
When this instance should be extensible by sub-classing
Singleton
Singleton Define an Instance operation to access its
unique instance. It must be a static method. Must create its own unique instance.
Singleton - benefits
Controlled access to sole instance Reduced namespace May be sub-classed to refine
operations Can Permit a variable number of
instances More flexible than static methods
Singleton – Implementation
Ensure a unique instanceclass Singleton {private: static Singleton* inst = 0 ;public: static Singleton* getInstance() { if (inst==0) inst = new Singleton() ; return inst ;}protected Singleton() { }
} ; Subclassing the singleton class
Put getInstance() method in each subclass
Singleton – Maze exampleclass MazeFactory {
protected: MazeFactory()
{ }
private: static MazeFactory* inst = null ;
public: static MazeFactory* getInst()
{ if (inst==null)
inst = new MazeFactory() ;
return inst ; }
Maze* makeMaze()
{ return new Maze() ; }
Room* makeRoom(int n)
{ return new Room(n) ; }
Wall* makeWall()
{ return new Wall() ; }
Door* makeDoor(Room r1, Room r2)
{ return new Door(r1,r2) ; }
} ;
Singleton – Maze exampleclass MazeGame{public:
Maze* createMaze() {Maze maze* = MazeFactory.getInst()->MakeMaze() ;Room room1* = MazeFactory.getInst()->MakeRoom(1) ;Room room2* = MazeFactory.getInst()->MakeRoom(2) ;Door door* = MazeFactory.getInst()->MakeDoor(room1,room2) ;
maze->AddRoom(room1) ;maze->AddRoom(room2) ;
room1->SetSide(Maze.NORTH,MazeFactory.getInst()-> MakeWall()) ;room1->SetSide(Maze.EAST ,door) ;room1->SetSide(Maze.SOUTH,MazeFactory.getInst()-> MakeWall()) ;room1->SetSide(Maze.WEST ,MazeFactory.getInst()-> MakeWall()) ;
room2->SetSide(Maze.NORTH,MazeFactory.getInst()-> MakeWall()) ;room2->SetSide(Maze.EAST ,MazeFactory.getInst()-> MakeWall()) ;room2->SetSide(Maze.SOUTH,MazeFactory.getInst()-> MakeWall()) ;room2->SetSide(Maze.WEST ,door) ;
return maze ;}
}
Singleton – Alternative Maze Factory
class MazeFactory {protected: MazeFactory()
{ }private: static final string name;private: static MazeFactory* inst = null ;public: static MazeFactory* getInst()
{ if (inst==null) {if (name=="BOMBED")
inst = new BombedMazeFactory() ;else
inst = new MazeFactory() ; } return inst ; }
// …}
Template Singleton Class// in .h
template <class T>class Singleton : public T{public:
static Singleton* GetInstance() {
if (! ptrSingObject) ptrSingObject = new Singleton ;
return ptrSingObject ; }~Singleton() { delete ptrSingObject ; }
private:Singleton() { } ;static Singleton* ptrSingObject ;
};// In .cpp
template <class T>Singleton<T>* Singleton<T>::ptrSingObject = NULL ;
// usageclass CMyClass {
void myfunc() ;} ;
// In the program to useSingleton<CMyClass>::GetInstance()->myfunc() ;