Upload
lindsay-kellie-thompson
View
236
Download
4
Tags:
Embed Size (px)
Citation preview
Creational PatternsCreational Patterns
CSE 8313
2
Creational PatternsCreational PatternsClass 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
The Maze GameThe Maze GamePopular videogameCenterpiece: a class that
generates maze layouts◦creates random mazes to be solved◦different for every game◦MazeGame
Maze creation processMaze creation process
Invoked for each game
5
Creational Patterns – Maze ExampleCreational Patterns – Maze Example
class MapSite {public: virtual void Enter() = 0;};
enum Direction {North, South, East, West};
6
Creational Patterns – Maze ExampleCreational 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
Creational Patterns – Maze ExampleCreational Patterns – Maze Exampleclass 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;
}
Maze creation process 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;
}// ...}
Change: game extensionsChange: game extensionsNew Features
◦ add new types of mazes to the game …◦ … without changing the overall logic
according to which the game works◦ in particular how it creates the mazes
Example: besides regular mazes◦ Add enchanted mazes◦ Add bombed mazes◦ … etc.
Solutions with current Solutions with current codecode
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 of createMaze()◦ createEnchantedMa
ze()◦ createBombedMaze
()2. Add switch/case
statements every time a constructor is invoked◦ based on some flag
variable3. …4. Re-factor!
Refactoring maze creationRefactoring maze creation
Factory Methods
Client still invokes this method
12
Creational Patterns – Maze ExampleCreational 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)
Class Creational PatternClass Creational Pattern
Factory methodsFactory methods
Each of the factory methods wraps the invocation 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();
}
Creating the mazeCreating the maze
Build Enchanted ProductsBuild Enchanted Products
Enchanted Maze CreatorEnchanted Maze Creator
createMaze()can still be invoked to
create regular mazes or enchanted mazes
without modification
Enchanted Maze CreatorEnchanted Maze Creator
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);}}
Build Bombed MazesBuild Bombed Mazes
r
Build Bombed MazesBuild 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
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!
Properties of this solutionProperties of this solutionThe client component in the game that
invokes the creation of mazes does not need to change
It interacts with different mazes creator classes◦ 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
The Factory Method patternThe Factory Method pattern- structure- structure
AdvantagesAdvantages
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 methodsThe 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
The Factory Method The Factory Method patternpattern
Classification:◦ Creational purpose; Class scope
Context: dynamic creation of different types of objects depending on context, transparent the client
Problem: a client class needs to instantiate one of many derivations of another class, but does not know which one.
Solution: define an interface for creation, and delegate to a derived class of that interface the decision of what class 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
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 The Factory Method patternpattern
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 The Factory Method patternpattern
28
Use Factory Method pattern when
◦a class can't anticipate the class of objects it must create◦a class wants its subclasses to specify the objects it creates
The Factory Method The Factory Method patternpattern
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 The Factory Method patternpattern
30
So what exactly does it mean when we say that "the Factory Method Pattern lets subclasses decide which class 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 The Factory Method patternpattern
31
Example 1: Clients can also use factory methods.
The factory method in this case is createManipulator()
The Factory Method The Factory Method patternpattern
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 The Factory Method patternpattern
33
The reason this works is that the createMaze() method of MazeGame defers the creation of maze objects to its subclasses. That's the Factory Method pattern at work! In this example, the correlations are:
◦ Creator => MazeGame◦ ConcreteCreator => EnchantedMazeGame (MazeGame is also a ConcreteCreator)◦ Product => MapSite◦ ConcreteProduct => Wall, Room, Door, EnchantedWall, EnchantedRoom, EnchantedDoor
The Factory Method The Factory Method patternpattern
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 of products? If so, then the factory method has a parameter (possibly used in an if-else!) to decide what object to create.
The Factory Method The Factory Method patternpattern
Factory Method in the real Factory Method in the real worldworldExample:iterator() in Java CollectionsDepending on the Collection type
being used, it returns the right iterator object◦which implements the right traversal
algorithm for that Collection
Object Creational Object Creational PatternsPatterns
Object Creational PatternsObject Creational PatternsAbstract object instantiationAdd one more level of
abstraction on top of OO languages
What’s the use of the extra abstraction layer?
Object Creational Patterns - Object Creational Patterns - motivationmotivation
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
enter the designThe extra layer of abstraction enables
to configure the system dynamically◦ Depending on the configuration, the
system will create those new types
Analogy: factoryAnalogy: factoryImagine a company with many
different products in the same product family◦ and 1 production plant: a factory
The more flexible the plant, the more successful the company’s business!
Analogy: factoryAnalogy: factoryYou want the capability of making different
products in 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 processResult: a different final product
Abstract Factory patternAbstract Factory patternAbstract FactorySimilar to Factory method
Let’s see the difference in our Maze game example …
MazeGame Abstract MazeGame Abstract FactoryFactory
MazeGame Abstract MazeGame Abstract FactoryFactory
The createMaze() now method takes a MazeFactory reference as a parameter
Enchanted Enchanted FeatureFeature
Bombed FeatureBombed FeatureMapSite
Door Wall Room
Maze
1
*1
*
SpellDoor EnchantedWall EnchantedRoom
+Maze makeMaze()+Wall makeWall()+Room makeRoom()+Door makeDoor()
MazeFactory
+Maze makeMaze()+Wall makeWall()+Room makeRoom()+Door makeDoor()
EnchantedMazeFactory
+Maze makeMaze()+Wall makeWall()+Room makeRoom()+Door makeDoor()
BombedMazeFactory
BombedDoor BombedWall BombedRoom
+Maze createMaze(in MazeFactory Factory)
MazeGameCreator
«uses»«uses» «uses»
Abstract Factory - structureAbstract Factory - structure
Dependency Inversion Dependency Inversion PrinciplePrinciple
Abstract Factory vs. Factory Abstract Factory vs. Factory MethodMethodSlightly more elegant than Factory
Method in our exampleWhere is the difference?In fact, very similar to the Factory
Method pattern◦ 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.
When to use Abstract Factory When to use Abstract Factory PatternPatternWhen a system should be independent
of how 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 you need to enforce this constraint
The Abstract Factory The Abstract Factory pattern pattern
Classification:◦ Creational purpose; Class scope
Context: there are multiple libraries or sets of classes that are to be chosen depending on context
Problem: families of related objects need to be instantiated together
Solution: coordinates the creation of objects of the same family. Client remains agnostic on the procedure and the rules about which object is in which 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
Real-world example: A GUI toolkit Real-world example: A GUI toolkit that supports multiple look-and-that supports multiple look-and-feelsfeels
Bullet PointsBullet PointsAll factories encapsulate object
creationFactory Method relies on
inheritance: object creation is delegated to subclasses which implement the factory method to create objects
All factory patterns promote loose coupling by reducing the dependency of your application on concrete classes
Bullet PointsBullet PointsThe intent of Factory Method is to
allow a class to defer instantiation to its subclasses
The intent of Abstract Factory is to create families of related objects without having to depend on their concrete classes.
Class recapClass recapCreational patterns
◦Factory method◦Abstract Factory◦Builder
Design PrinciplesDesign PrinciplesOpen Close PrincipleDependency Inversion
◦A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
◦B. Abstractions should not depend upon details. Details should depend upon abstractions.
Information Hiding