Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

35
Creational Patterns, Creational Patterns, Abstract Factory, Abstract Factory, Builder Builder Billy Bennett June 11, 2009

Transcript of Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Page 1: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Creational Patterns,Creational Patterns,Abstract Factory,Abstract Factory,BuilderBuilder

Billy BennettJune 11, 2009

Page 2: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Creational PatternsCreational Patterns

Two Recurring Themes:

1.Encapsulate knowledge about which concrete classes the system uses.

2.Hide how these instances are created and put together.

Page 3: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

The Maze ExampleThe Maze Example

Page 4: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Maze* MazeGame::CreateMaze ()

{

Maze* aMaze = new Maze;

Room* r1 = new Room (1);

Room* r2 = new Room (2);

Door* theDoor = new Door (r1, r2);

aMaze->AddRoom(r1);

aMaze->AddRoom(r2);

r1->SetSide(North, new Wall);

r1->SetSide(East, theDoor);

r1->SetSide(South, new Wall);

r1->SetSide(West, new Wall);

r2->SetSide(North, new Wall);

r2->SetSide(East, new Wall);

r2->SetSide(South, new Wall);

r2->SetSide(West, theDoor);

return aMaze;

}

Page 5: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Uh-ohUh-ohThis gets complicated.It’s inflexibly coded.It’s difficult to reuse.Only makes 2 rooms.Creational patterns let us make

this design more flexible and thus more reusable.

Page 6: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Potential PatternsPotential PatternsVirtual functions instead of

constructors for◦Rooms◦Doors◦Walls

Make a subclass of MazeGame to redefine these functions

Factory Method

Page 7: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Potential PatternsPotential PatternsCreateMaze is passed an object

as a parameter, which is used to change the classes used to make◦Rooms◦Doors◦Walls

Abstract Factory

Page 8: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Potential PatternsPotential PatternsCreateMaze is passed an object

that can create a maze all by itself, then you can use inheritance to change parts of the maze:◦Rooms◦Doors◦Walls

Builder

Page 9: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Potential PatternsPotential PatternsCreateMaze is parameterized by

various prototypical:◦Rooms◦Doors◦Walls

You can replace these prototypical objects with different ones to change the maze

Prototype

Page 10: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Abstract FactoryAbstract Factory

Page 11: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Abstract FactoryAbstract FactoryIntent

◦Provide an interface for creating families of related or dependent objects without specifying their concrete classes

A.K.A.◦“Kit”

Page 12: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ApplicabilityApplicabilityA system should be independent of

how its products are created, composed, or represented

A system should be configured with one of multiple families of products

A family of related product objects is designed to be used together

You want to provide a class library of objects, but reveal only their interfaces

Page 13: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.
Page 14: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ParticipantsParticipantsClientAbstractFactoryConcreteFactoryAbstractProductConcreteProduct

Page 15: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

1. Concrete class isolation (Good)• Client does not interact with the

implementation classes• Client only manipulates instances

through the abstract interfaces

Page 16: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

2. Product families easily exchanged (Good)• Only have to change the concrete

factory• Can be done at run time

Page 17: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

3. Products are more consistent (Good)• Helps the products in each product

family consistently be applied together (assuming they work well together)

• Only one family at a time

Page 18: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

4. Difficult to support new kinds of products (Bad)• Extending existing abstract

factories to make new products is difficult and time consuming

• The family of products available is fixed by Abstract Factory interface

Page 19: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Implementation IssuesImplementation IssuesConcrete Factories make excellent

Singletons (not necessarily one factory, but one per product family)

Factory Methods within Concrete Factories for each product, or Prototypes if many product families

Move implementation one step closer to Client by adding a parameter specifying product type (less safe, more extensible)

Page 20: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Class MazeFactory {

Public:

MazeFactory();

virtual Maze* MakeMaze () const

{return new Maze;}

virtual Wall* MakeWall () const

{return new Wall;}

virtual Room* MakeRoom (int n) const

{return new Room(n);}

virtual Door* MakeDoor (Room* r1, Room* r2)

{return new Door(r1, r2);}

};

Page 21: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Maze* MazeGame::CreateMaze ()

{

Maze* aMaze = new Maze;

Room* r1 = new Room (1);

Room* r2 = new Room (2);

Door* theDoor = new Door (r1, r2);

aMaze->AddRoom(r1);

aMaze->AddRoom(r2);

r1->SetSide(North, new Wall);

r1->SetSide(East, theDoor);

r1->SetSide(South, new Wall);

r1->SetSide(West, new Wall);

r2->SetSide(North, new Wall);

r2->SetSide(East, new Wall);

r2->SetSide(South, new Wall);

r2->SetSide(West, theDoor);

return aMaze;

}

Page 22: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Maze* MazeGame::CreateMaze (MazeFactory& factory)

{

Maze* aMaze = factory.MakeMaze();

Room* r1 = factory.MakeRoom (1);

Room* r2 = factory.MakeRoom (2);

Door* theDoor = factory.MakeDoor (r1, r2);

aMaze->AddRoom(r1);

aMaze->AddRoom(r2);

r1->SetSide(North, factory.MakeWall);

r1->SetSide(East, theDoor);

r1->SetSide(South, factory.MakeWall);

r1->SetSide(West, factory.MakeWall);

r2->SetSide(North, factory.MakeWall);

r2->SetSide(East, factory.MakeWall);

r2->SetSide(South, factory.MakeWall);

r2->SetSide(West, theDoor);

return aMaze;

}

Page 23: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Related PatternsRelated PatternsFactory MethodPrototypeSingleton

Page 24: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

BuilderBuilderIntent

◦Separate the construction of a complex object from its representation so that the same construction process can create different representations

Page 25: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ApplicabilityApplicabilityThe algorithm for creating a

complex object should be independent of the parts that make up the object and how they’re assembled

The construction process must allow for different representations for that object that’s constructed

Page 26: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.
Page 27: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.
Page 28: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ParticipantsParticipantsDirectorBuilderConcrete BuilderProduct

Page 29: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

1. Varying a product’s internal representation (Good)• The Director doesn’t see the

product’s construction, only the Builder does

Page 30: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

2. Isolates code for construction and representation (Good)• The Client only retrieves the

product• The Client doesn’t know anything

about the internal construction of the product

• Question: Multiple directors?

Page 31: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

ConsequencesConsequences

3. Step by step construction (Good?)• The Client only retrieves the

product• The Client doesn’t know anything

about the internal construction of the product

• Question: Multiple directors?

Page 32: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Implementation IssuesImplementation IssuesBuilder needs a very general

interfaceBuilder(s) may need access to a

variety of components – parse trees are one solution

No abstract product class (products are too different, commonly)

Page 33: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Class MazeBuilder {

public:

virtual void BuildMaze() {. . .}

virtual void BuildRoom (int room) {. . .}

virtual void BuildDoor (int roomFrom, int roomTo) {. . .}

virtual Maze* GetMaze() {return Maze to client}

Protected:

MazeBuilder();

};

Page 34: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Maze* MazeGame::CreateMaze (MazeBuilder& builder)

{

builder.BuildMaze();

builder.BuildRoom(1);

builder.BuildRoom(2);

builder.BuildDoor(1,2);

return builder.GetMaze();

}

Page 35: Creational Patterns, Abstract Factory, Builder Billy Bennett June 11, 2009.

Other thoughtsOther thoughtsThe “abstract interface” theme

among patternsOOP bias?Why do some patterns seem so

similar – is there a standard for defining novelty among patterns?