05_creationalpatterns1.ppt
TRANSCRIPT
-
7/27/2019 05_CreationalPatterns1.ppt
1/55
Creational Patterns
CSE 8313
-
7/27/2019 05_CreationalPatterns1.ppt
2/55
2
Creational Patterns
Class creational pattern uses inheritance to vary the class that is instantiated
Object creational pattern
delegates instantiation to another object
Systems evolve to depend more on object
composition than class inheritance
Two recurring themes: Encapsulate knowledge about which concrete classes the system
uses
Hide how instances of these classes are created and put together
-
7/27/2019 05_CreationalPatterns1.ppt
3/55
The Maze Game
Popular videogame Centerpiece: a class that generates
maze layouts
creates random mazes to be solved different for every game
MazeGame
-
7/27/2019 05_CreationalPatterns1.ppt
4/55
Maze creation process
Invoked for each game
-
7/27/2019 05_CreationalPatterns1.ppt
5/55
5
Creational Patterns Maze Example
class MapSite {
public:
virtual void Enter() = 0;
};
enum Direction {North, South, East, West};
-
7/27/2019 05_CreationalPatterns1.ppt
6/55
6
Creational Patterns Maze Example
class Room : public MapSite {
public:
Room(int roomNo);
MapSite* GetSide(Direction) const;
void SetSide(Direction, MapSite*);
virtual void Enter();
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;
};
-
7/27/2019 05_CreationalPatterns1.ppt
7/557
Creational Patterns Maze Example
class Maze {
public:
Maze();
void AddRoom(Room*);
Room* RoomNo(int) const;
private:
// ...
};
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;
}
-
7/27/2019 05_CreationalPatterns1.ppt
8/55
Maze creation process
public class MazeGame {
public MazeGame() {...}
public Maze 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(MapSite.NORTH, new Wall());
r1.setSide(MapSite.EAST, theDoor);
r1.setSide(MapSite.SOUTH, new Wall());
r1.setSide(MapSite.WEST, new Wall());r2.setSide(MapSite.NORTH, new Wall());
r2.setSide(MapSite.EAST, new Wall());
r2.setSide(MapSite.SOUTH, new Wall());
r2.setSide(MapSite.WEST, theDoor);
return aMaze;
}
// ...}
-
7/27/2019 05_CreationalPatterns1.ppt
9/55
Change: game extensions
New Features add new types of mazes to the game
without changing the overall logic according towhich the game works
in particular how it creates the mazes Example: besides regular mazes
Add enchanted mazes
Add bombed mazes
etc.
-
7/27/2019 05_CreationalPatterns1.ppt
10/55
Solutions with current code
public class MazeGame {public MazeGame() {...}
public Maze 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(MapSite.NORTH, new Wall());r1.setSide(MapSite.EAST, theDoor);r1.setSide(MapSite.SOUTH, new
Wall());r1.setSide(MapSite.WEST, new
Wall());r2.setSide(MapSite.NORTH, new
Wall());r2.setSide(MapSite.EAST, new
Wall());r2.setSide(MapSite.SOUTH, new
Wall());r2.setSide(MapSite.WEST, theDoor);
return aMaze;}// ...
}
1. Duplicate code ofcreateMaze() createEnchantedMaz
e()
createBombedMaze()2. Add switch/case
statements everytime a constructor is
invoked based on some flag
variable
3. 4. Re-factor!
-
7/27/2019 05_CreationalPatterns1.ppt
11/55
Refactoring maze creation
Factory Methods
Client still invokes this method
-
7/27/2019 05_CreationalPatterns1.ppt
12/5512
Creational Patterns Maze Example
CreateMaze calls virtual functions instead of constructor calls to
create the rooms, walls, and doors (Factory Method pattern) CreateMaze is passed an object as a parameter to use to create
rooms, walls, and doors (Abstract Factory pattern)
CreateMaze is passed an object that can create a new maze in its
entirety using operations for adding rooms, doors, and walls to the
maze it builds (Builder pattern)
CreateMaze is parameterized by various prototypical room, door,
and wall objects to be copied and added to the maze (Prototype
pattern)
-
7/27/2019 05_CreationalPatterns1.ppt
13/55
Class Creational Pattern
-
7/27/2019 05_CreationalPatterns1.ppt
14/55
Factory methods
Each of the factory methods wraps theinvocation of corresponding constructor
A set of methods that can be inherited and
overridden Examples (See Code):
Room makeRoom(int id) {
return new Room(id);
}
Wall makeWall() {
return new Wall();
}
-
7/27/2019 05_CreationalPatterns1.ppt
15/55
Creating the maze
-
7/27/2019 05_CreationalPatterns1.ppt
16/55
Build Enchanted Products
-
7/27/2019 05_CreationalPatterns1.ppt
17/55
Enchanted Maze Creator
createMaze()can still be invoked to
create regular mazes or
enchanted mazes
without modification
-
7/27/2019 05_CreationalPatterns1.ppt
18/55
-
7/27/2019 05_CreationalPatterns1.ppt
19/55
Build Bombed Mazes
r
-
7/27/2019 05_CreationalPatterns1.ppt
20/55
Build Bombed Mazes
MapSite
Door Wall Room
Maze
1
*1
*
SpellDoor EnchantedWall EnchantedRoom
+Maze createMaze()
+Maze makeMaze()
+Wall makeWall()
+Room makeRoom()
+Door makeDoor()
MazeGameCreator
+Maze makeMaze()
+Wall makeWall()
+Room makeRoom()
+Door makeDoor()
EnchantedMazeCreator
+Maze makeMaze()
+Wall makeWall()
+Room makeRoom()
+Door makeDoor()
BombedMazeCreator
BombedDoor BombedWall BombedRoom
createcreate
create
-
7/27/2019 05_CreationalPatterns1.ppt
21/55
21
We made createMaze() just slightly more complex, but a
lot more flexible! Consider this EnchantedMazeGame class:
public class EnchantedMazeGame extends MazeGame {
public Room makeRoom(int n) {return new EnchantedRoom(n);}
public Wall makeWall() {return new EnchantedWall();}
public Door makeDoor(Room r1, Room r2){return new EnchantedDoor(r1, r2);}
}
The createMaze() method of MazeGame is inherited by
EnchantedMazeGame and can be used to create regular
mazes or enchanted mazes without modification!
-
7/27/2019 05_CreationalPatterns1.ppt
22/55
Properties of this solution
The client component in the game thatinvokes the creation of mazes does not needto change
It interacts with different mazes creatorclasses Depending which extension has been selected by
the player
in exactly the same way as in the original game
Caveat: Recall we need a global flag that tells us which
MazeCreator subclass we need to instantiate in
every game
-
7/27/2019 05_CreationalPatterns1.ppt
23/55
The Factory Method pattern
- structure
-
7/27/2019 05_CreationalPatterns1.ppt
24/55
Advantages
The Creator provides a factory method that
substitute constructor of ConcreteProducts
The business logic of product creation, initialization
etc. can be wholly encapsulated in those methods
The client of Creator can ask for the
production of different Products in a uniform
way
And use them uniformly (all derive from main
Product super-class)
Without needing to know the nitty-gritty details
-
7/27/2019 05_CreationalPatterns1.ppt
25/55
The Factory Method pattern
Classification:
Creational purpose; Class scope
Context: dynamic creation of different types of objectsdepending on context, transparent the client
Problem: a client class needs to instantiate one ofmany derivations of another class, but does not knowwhich one.
Solution: define an interface for creation, and delegateto a derived class of that interface the decision of whatclass to instantiate and how
Consequences:
Need for parallel Product/Creator hierarchies
The logic of creating a particular types of product is
encapsulated in each Creator
-
7/27/2019 05_CreationalPatterns1.ppt
26/55
26
Intent:
Define an interface for creating an object, but let
subclasses decide which class to instantiate. Factory
Method lets a class defer instantiation to subclasses.
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
27/55
27
Motivation: consider a framework for applications that
can present multiple documents to the user
The createDocument() method is a factory method.
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
28/55
28
Use Factory Method pattern when
a class can't anticipate the class of objects itmust create
a class wants its subclasses to specify the
objects it creates
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
29/55
29
Structure and Participants
Collaborations
Creator relies on its subclasses to implement the factory method
so that it returns an instance of the appropriate ConcreteProduct
(Document)
(MyDocument)
(Application)
(My Application)
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
30/55
30
So what exactly does it mean when we say that "the
Factory Method Pattern lets subclasses decide whichclass to instantiate?"
It means that Creator class is written without knowing what actual
ConcreteProduct class will be instantiated. The ConcreteProduct
class which is instantiated is determined solely by which
ConcreteCreator subclass is instantiated and used by the
application.
It does not mean that somehow the subclass decides at runtime
which ConreteProduct class to create
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
31/55
-
7/27/2019 05_CreationalPatterns1.ppt
32/55
32
Example 2: MazeGame Revisit
class MazeGame {
public:
Maze* CreateMaze();
// factory methods:
virtual Maze* MakeMaze() const
{ return new Maze; }virtual Room* MakeRoom(int n) const
{ return new Room(n); }
virtual Wall* MakeWall() const
{ return new Wall; }
virtual Door* MakeDoor(Room* r1, Room* r2) const
{ return new Door(r1, r2); }};
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
33/55
33
The reason this works is that the createMaze() method
of MazeGame defers the creation of maze objects to itssubclasses. That's the Factory Method pattern at work!
In this example, the correlations are:
Creator => MazeGame
ConcreteCreator => EnchantedMazeGame (MazeGame is also aConcreteCreator)
Product => MapSite
ConcreteProduct => Wall, Room, Door, EnchantedWall,
EnchantedRoom, EnchantedDoor
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
34/55
34
Consequences
Benefits Code is made more flexible and reusable by the elimination of instantiation of
application-specific classes
Code deals only with the interface of the Product class and can work with any
ConcreteProduct class that supports this interface
Liabilities Clients might have to subclass the Creator class just to instantiate a particular
ConcreteProduct
Implementation Issues
Creator can be abstract or concrete
Should the factory method be able to create multiple kinds ofproducts? If so, then the factory method has a parameter
(possibly used in an if-else!) to decide what object to create.
The Factory Method pattern
-
7/27/2019 05_CreationalPatterns1.ppt
35/55
-
7/27/2019 05_CreationalPatterns1.ppt
36/55
Object Creational Patterns
-
7/27/2019 05_CreationalPatterns1.ppt
37/55
Object Creational Patterns
Abstract object instantiationAdd one more level of abstraction on
top of OO languages
Whats the use of the extra abstractionlayer?
-
7/27/2019 05_CreationalPatterns1.ppt
38/55
Object Creational Patterns -
motivation
Evolution and extendibility of the system Do not hardcode object creation
Type selection is static when using constructor
Prepare for more types of similar objects to enterthe design
The extra layer of abstraction enables to
configure the system dynamically
Depending on the configuration, the system willcreate those new types
-
7/27/2019 05_CreationalPatterns1.ppt
39/55
Analogy: factory
Imagine a company with many differentproducts in the same product family
and 1 production plant: a factory
The more flexible the plant, the moresuccessful the companys business!
-
7/27/2019 05_CreationalPatterns1.ppt
40/55
Analogy: factory
You want the capability of making different productsin the same production plant
Simply by hitting a switch
The production procedure followed by the factory is
the same independent from the product being produced
the switch controls what machinery is activated during the
production process
Result: a different final product
-
7/27/2019 05_CreationalPatterns1.ppt
41/55
Abstract Factory pattern
Abstract Factory Similar to Factory method
Lets see the difference in our Maze
game example
MazeGame Abstract Factory
-
7/27/2019 05_CreationalPatterns1.ppt
42/55
MazeGame Abstract Factory
-
7/27/2019 05_CreationalPatterns1.ppt
43/55
MazeGame Abstract Factory
The createMaze() now method takes a MazeFactory
reference as a parameter
-
7/27/2019 05_CreationalPatterns1.ppt
44/55
Enchanted
Feature
-
7/27/2019 05_CreationalPatterns1.ppt
45/55
-
7/27/2019 05_CreationalPatterns1.ppt
46/55
Abstract Factory - structure
-
7/27/2019 05_CreationalPatterns1.ppt
47/55
Dependency InversionPrinciple
Ab t t F t F t
-
7/27/2019 05_CreationalPatterns1.ppt
48/55
Abstract Factory vs. Factory
Method Slightly more elegant than Factory Method
in our example
Where is the difference?
In fact, very similar to the Factory Methodpattern
in Abstract Factory, a class delegates the
responsibility of object instantiation to another
one via composition the Factory Method pattern uses inheritance to
handle the desired object instantiation.
-
7/27/2019 05_CreationalPatterns1.ppt
49/55
When to use Abstract Factory
Pattern
When a system should be independent ofhow its products are created, composed,and represented
When a class can't anticipate the class of
objects it must create When a system must use just one of a
multiple families of product objects
When a family of related product objects is
designed to be used together, and youneed to enforce this constraint
-
7/27/2019 05_CreationalPatterns1.ppt
50/55
The Abstract Factory pattern
Classification: Creational purpose; Class scope
Context: there are multiple libraries or sets ofclasses that are to be chosen depending on context
Problem: families of related objects need to beinstantiated together
Solution: coordinates the creation of objects of thesame family. Client remains agnostic on theprocedure and the rules about which object is inwhich family
Consequences: The logic of creating a particular object family is kept hidden
from client
Enforces family rules
Supporting new product requires changing the
AbstractFactory interface
-
7/27/2019 05_CreationalPatterns1.ppt
51/55
Real-world example: A GUI toolkit that
supports multiple look-and-feels
-
7/27/2019 05_CreationalPatterns1.ppt
52/55
Bullet PointsAll factories encapsulate object
creation
Factory Method relies on inheritance:
object creation is delegated tosubclasses which implement thefactory method to create objects
All factory patterns promote loose
coupling by reducing the dependencyof your application on concreteclasses
-
7/27/2019 05_CreationalPatterns1.ppt
53/55
Bullet Points The intent of Factory Method is to
allow a class to defer instantiation to
its subclasses
The intent of Abstract Factory is tocreate families of related objects
without having to depend on their
concrete classes.
-
7/27/2019 05_CreationalPatterns1.ppt
54/55
Class recap
Creational patterns Factory method
Abstract Factory
Builder
-
7/27/2019 05_CreationalPatterns1.ppt
55/55
Design Principles
Open Close Principle Dependency Inversion
A. High-level modules should not depend
on low-level modules. Both shoulddepend on abstractions.
B. Abstractions should not depend upon
details. Details should depend upon
abstractions.
Information Hiding