Upload
ramona-smith
View
27
Download
4
Embed Size (px)
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
Citation preview
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 - 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 – 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 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 – 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 – 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.