02 - Creational Design Patterns – 2

29
02 - Creational Design Patterns – 2 Moshe Fresko Bar-Ilan University חחח"ח2008

description

02 - Creational Design Patterns – 2. Moshe Fresko Bar-Ilan University תשס"ח 2008. Builder. Moshe Fresko Bar-Ilan University תשס"ו - 2005-2006 Design Patterns Course. Builder. - PowerPoint PPT Presentation

Transcript of 02 - Creational Design Patterns – 2

02 - Creational Design Patterns – 2

Moshe Fresko

Bar-Ilan University

תשס"ח

2008

Builder

Moshe Fresko

Bar-Ilan University

2005-2006 - תשס"ו

Design Patterns Course

Builder Intent: Separate the construction of a complex object from its

representation so that the same construction process can create different representations.

Motivation: An RTF reader should be able to convert an RTF document to

many text formats. The number of possible conversions are open-ended.

Plain ASCII Text Text Widget for Editing

RTF-Reader parses the RTF document. It uses Text-Converter to perform the conversion.

Whenever the RTF-Reader recognizes an RTF token it issues a request to the Text-Converter to convert the token.

Builder – Motivation

Each converter class is called a Builder, and the reader is called the Director.

Builder – Applicability

Use the Builder pattern when The algorithm for creating a complex object

should be independent of the parts that make up the object and how they are assembled.

The construction process must allow different representations for the object that is constructed.

Builder – Structure

Builder - Participants

Builder (TextConverter) Specifies an abstract interface for creating parts of a

product object. ConcreteBuilder (AsciiConverter, TeXConverter, …)

Constructs and assembles parts of products Defines and keeps track of the representation it creates Provides an interface for retrieving the product

Director (RTFReader) Constructs an object using the Builder interface

Product (AsciiText, TeXText, …) Represents the complex object under construction

Builder – Director cooperation

Builder – Consequences

1. It let’s you vary a product’s internal representation

2. It isolates code for construction and representation

3. It gives you finer control over the construction process

Builder – Implementation Issues

1. Assembly and Construction Interface Builders construct their products step-by-step.

Usually appending simply the parts is enough. Sometimes access to parts is needed. (Door

between rooms, children nodes for a tree structures)

2. Why no abstract class for products? The products differ greatly. The client configures the director with the

concrete builder.

3. Empty methods as default in builder.

Builder – Sample Codeclass MazeBuilder {public:

virtual void BuildMaze() { }virtual void BuildRoom(int n) { }virtual void BuildDoor(int nfrom, int nto) { }virtual Maze* GetMaze() { return 0 ; }

protected:MazeBuilder() ;

} ;

Maze* MazeGame::CreateMaze(MazeBuilder& builder) {builder.BuildMaze() ;builder.BuildRoom(1) ;builder.BuildRoom(2) ;builder.BuildDoor(1,2) ;return builder.GetMaze() ;

}

Builder – Sample Code

Maze* MazeGame::CreateComplexMaze ( MazeBuilder& builder) {

builder.BuildMaze() ;

builder.BuildRoom(1) ;

builder.BuildRoom(2) ;

builder.BuildDoor(1,2) ;

builder.BuildRoom(1000) ;

return builder.GetMaze() ;

}

Builder – Sample Codeclass StandardMazeBuilder : public MazeBuilder {private:

Maze* currentMaze ;public:

StandardMazeBuilder() : currentMaze(0) { }

virtual void BuildMaze(){ currentMaze = new Maze() ; }

Maze* GetMaze(){ return currentMaze ; }

virtual void BuildRoom(int n){ if (! currentMaze->RoomNo(n)) { Room* room = new Room(n) ; currentMaze->AddRoom(room) ; room->SetSide(North, new Wall()) ; room->SetSide(South, new Wall()) ; room->SetSide(East , new Wall()) ; room->SetSide(West , new Wall()) ; }}

virtual void BuildDoor(int n1,int n2) {Room* r1 = currentMaze->RoomNo(n1) ;Room* r2 = currentMaze->RoomNo(n2) ; Door* d = new Door(r1,r2) ; r1->SetSide(CommonWall(r1,r2),d) ; r2->SetSide(CommonWall(r2,r1),d) ;

}} ;

Builder – Sample Code

UsageMaze* maze;

MazeGame game;

StandardMazeBuilder builder;

game.CreateMaze(builder);

maze = builder.GetMaze();

Builder – Sample Code Another builder for countingclass CountingMazeBuilder : public MazeBuilder {private:

int doors;int rooms;

public:CountingMazeBuilder(): doors(0), rooms(0)

{ }virtual void BuildMaze()

{ doors=0; rooms=0; }virtual void BuildRoom(int i)

{ rooms++; }virtual void BuildDoor(int r1,int r2)

{ doors++; }void GetCounts(int& roomcount, int& doorcount)

{ roomcount=rooms; doorcount=doors; }};

Builder – Sample Code

int rooms, doors;

MazeGame game;

CountingMazeBuild builder;

game.CreateMaze(builder);

builder.GetCounts(rooms,doors);

cout << “The maze has ”

<< rooms << “ rooms and ”

<< doors << “ doors” << endl ;

Prototype

Moshe Fresko

Bar-Ilan University

2005-2006 - תשס"ו

Design Patterns Course

Prototype Intent: Specify the kinds of objects to create using a

prototypical instance, and create new objects by copying this prototype.

Motivation: To build an editor for music scores by customizing a general

framework for graphical editors and adding new objects that represent notes, rests and staves.

Let’s have a Graphic class for graphic components like notes (a quarter-note), staves, etc. And a GraphicTool class for adding such components.

The classes of notes and staves are specific to application and GraphicTool is a general framework. Subclassing GraphicTool needs a subclass for each Graphic class. It is better to use composition.

Solution is to add a cloning instance (Prototype) into GraphicTool.

Prototype – Motivation

Prototype – Applicability

Use Prototype pattern when a system should be independent of how its products are created, composed, and represented; and When the classes to instantiate are specified at

run-time To avoid building class-hierarchy of factories that

parallels the class hierarchy of products When instances of a class can have only one of a

few different combinations of states.

Prototype – Structure

Prototype – Participants

Prototype (Graphic) Declares an interface for cloning itself

ConcretePrototype (Staff, WholeNote, HalfNote) Implements an operation for cloning itself

Client (GraphicTool) Creates a new object by asking a prototype to clone itself.

Prototype – Consequences

It hides concrete product classes from the client Let a client work with application-specific classes

without modification1. Adding and removing products at run-time.2. Specifying new objects by varying values.3. Specifying new objects by varying structure.4. Reduced subclassing.5. Configuring an application with classes

dynamically. Adding Clone() to each product may be difficult.

Prototype – Implementation Issues

1. Using a prototype manager. To keep a registry of possible prototypes.

2. Implementing the Clone operation. Shallow Copy versus Deep Copy.Serialization (Save-Load) can be used for cloning.

3. Initializing clones.Set operations can solve this problem.

Prototype – Sample

class MazePrototypeFactory : public MazeFactory {private:

Maze* pMaze; Wall* pWall; Room* pRoom; Door* pDoor;public:

MazePrototypeFactory ( Maze* m, Wall* w, Room* r, Door* d) : pMaze(m), pWall(w), pRoom(r), pDoor(d) { }

virtual Maze* MakeMaze() const{ return pMaze->Clone() ; }

virtual Room* MakeRoom(int r) const{ Room* p = pRoom->Clone() ; p->initialize(r) ; return p; }

virtual Wall* MakeWall() const{ return pWall->Clone(); }

virtual Door* MakeDoor(Room* r1, Room* r2) const{ Door* door = pDoor->Clone(); door->initialize(r1,r2); return door; }

};

Prototype – Sample

MazeGame game;

MazePrototypeFactory simpleMazeFactory(new Maze, new Wall, new Room, new Door);

MazePrototypeFactory bombedMazeFactory(new Maze, new BombedWall, new RoomWithABomb, new Door);

Maze* maze1 = game.CreateMaze(simpleMazeFactory);

Maze* maze2 = game.CreateMaze(bombedMazeFactory);

Prototype – Sample class Door: public MapSite {private:

Room* room1;Room* room2;

public:Door(): room1(0), room2(0)

{ }Door(const Door& d): room1(d.room1), room2(d.room2)

{ }virtual void Initialize(Room* r1, Room* r2)

{ room1 = r1 ; room2 = r2 ; }

virtual Door* Clone() const {return new Door(*this) ;

}} ;

Prototype – Sample Codeclass BombedWall: public Wall {private:

bool bomb;public:

BombedWall() : bomb(true){ }

BombedWall(bool b) : bomb(b){ }

BombedWall(const BombedWall& other){ bomb = other.bomb; }

virtual Wall* Clone() const{ return new BombedWall(*this) ; }

bool HasBomb(){ return bomb; }

} ;

Creational Design Patterns – Discussion

Two ways two parameterize a system by the classes of objects it creates.

1. To subclass the class that creates objects- Factory MethodMain drawback is that it requires a new subclass just to change the class of the product.

2. By object composition- Abstract Factory: Factory Object producing objects of several classes- Builder: Factory Object building a complex product- Prototype: Factory Object building a product by copying a prototype object.