02 - creational design patterns moshe fresko bar-ilan university תשס"ח 2008
Post on 30-Dec-2015
219 Views
Preview:
TRANSCRIPT
02 - Creational Design Patterns
Moshe Fresko
Bar-Ilan University
תשס"ח
2008
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. Creational
2. Behavioral
3. Structural
Creational Design Patterns
Creational DP: Abstracts the instantiation process. Help make a system independent of how objects are
created, composed, represented.
Two types of Creational Patterns 1. Class creational patterns
Use inheritance to vary the class that is instantiated
2. Object creational patternsDelegates instantiation to another object
Creational Design Patterns
Two recurring themes in these patterns1. They encapsulate knowledge about which concrete
classes the system use.2. They hide how instances of these classes are created
and put together. The system only knows the interfaces. Creational DP-s let you configure the system with
“product” objects Configuration can be static (compile-time) or dynamic
(run-time).
Example: To build a Maze
Maze Example – MapSite Abstract class
enum Direction
{ North, South, East, West } ;
class MapSite {
public:
void Enter() = 0 ;
} ;
Maze Example – Roomclass Room: public MapSite { public: Room(int roomNo) ; { roomNumber = number ; } MapSite* GetSide(Direction d) const { return sides[d] ; } void SetSide(Direction d, MapSite* m) { sides[d] = m ; } virtual void Enter() { /* … do something … */ } private: MapSite* sides[4] ; int roomNumber ; } ;
Maze Example – Wall and Door
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 Example – Collection of Rooms
class Maze {
public:
Maze() ;
void addRoom(Room r) ;
Room* RoomNo(int) const;
private:
// …
};
Maze Example – Creation of Mazeclass 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 ;}
}
Room 1 Room 2
Creational Patterns Factory Method
Create-Maze calls virtual functions to create components Abstract Factory
Create-Maze is passed an object to use to create components
Prototype Create-Maze is parameterized by various prototypes
Builder Create-Maze is passed an object that can create entire
Maze Singleton
Can ensure that there is only one maze per game.
Factory Method
Moshe Fresko
Bar-Ilan University
2005-2006 - תשס"ו
Design Patterns Course
Factory Method
Intent: Define an interface for creating an object, but let subclasses decide which class 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 instantiate
Concrete classes: DrawingDocument, DrawingApplication
Factory Method encapsulates the knowledge of which Document subclass to create and move this knowledge out of the framework.
Factory Method – Motivation
CreateDocument() is called Factory Method
Factory Method – Maze Exampleclass 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 ;
}} ;
Factory Method – Maze, Customized Components
class 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) ; }} ;
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 Classes delegate responsibility to one of several
helper subclasses and you want to localize the knowledge of which helper subclass is the delegate
Factory Method – Structure
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 – Consequences
Eliminates the need to bind application-specific classes into the code.
Disadvantage: Clients might have to subclass the Creator class just to create a particular ConcreteProduct.
Provides hooks for subclasses to create extended version of an object.
Connects parallel class hierarchies.
Factory Method – Implementation Issues
1. Two Major Varieties Creator class has abstract factory methods Creator class defines default behavior for factory methods
2. Parameterized Factory Methods One factory method can create multiple kinds of products. All objects must have the same interface. Factory method can take a class ID.
3. Language-specific issues. Creator can keep the Class information for creating new
instances, dropping the need for the sub-classing.
4. Templates can be used to avoid subclassing.
Abstract Factory
Moshe Fresko
Bar-Ilan University
2005-2006 - תשס"ו
Design Patterns Course
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
Widget Factory enforces dependencies between the concrete Widget classes
Abstract Factory Example
Factory Method – Maze Exampleclass 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 ;
}} ;
Factory Method – Maze Exampleclass 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) ; }} ;
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 – Consequences
1. It isolates concrete classes
2. It makes exchanging product families easy
3. It promotes consistency among products
4. Supporting new kinds of products is difficult
Abstract Factory – Implementation
Factory better to be a Singleton If many product families are possible, the Concrete
Factory can be implemented using Prototype. Or alternatively the Class information of products can be kept (for languages supporting Class information).
Defining Extensible Factories: Adding a new Product type means to change AbstractFactory and all its subclasses. A more flexible but less safe design is to add a parameter to operations that create objects.
Singleton
Moshe Fresko
Bar-Ilan University
2005-2006 - תשס"ו
Design Patterns Course
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
1. Controlled access to sole instance
2. Reduced namespace
3. May be sub-classed to refine operations
4. Can Permit a variable number of instances
5. More flexible than static methods
Singleton – Implementation
Ensure a unique instanceclass Singleton {private: static Singleton* inst = 0 ;protected: Singleton() { }public: static Singleton* getInstance() { if (inst==0) inst = new Singleton() ; return inst ;}
} ; Subclassing the singleton class
How to install the unique instance? To determine it in getInstance() method To rewrite getInstance() in the subclass To keep registry of Singletons
Singleton –Maze Factory
class 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) ;………return maze ;
}}
Singleton – Alternative Maze Factory
MazeFactory* MazeFactory::getInst() { if (inst==0) {
const char* style = getenv("MAZESTYLE") ; if (strcmp(style,"BOMBED“))
inst = new BombedMazeFactory() ;else if (strcmp(style,"BOMBED“))
inst = new EnchantedMazeFactory() ; 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() ;
top related