Class 7 DP Creational
Class 7 DP Creational
Creational Patterns
Software Engineering 2012
Department of Computer Science Ben-Gurion university
Based on slides of: Mira Balaban Department of Computer Science Ben-Gurion university
F. Tip. IBM T J Watson Research Center.
Creational Patterns
purpose
abstract the process of creating objects
make a system unaware of how objects are created, composed,
and represented
what they do
encapsulate knowledge about which concrete classes a system
uses (access created objects via interfaces)
hide how instances are created
provide flexibility w.r.t.
types of created objects
responsibility for creation
how and when objects are created
South
class MapSite {
...
}
Class Room (1)
class Room extends MapSite {
Room(){
_roomNr = _roomCnt++;
System.out.println("creating Room #" + _roomNr);
}
if (d == Direction.North){
_northSide = site;
} else if (d == Direction.South){
_southSide = site;
} else if (d == Direction.East){
_eastSide = site;
} else if (d == Direction.West){
_westSide = site;
}
System.out.println("setting " + d.toString() +
" side of " + this.toString() + " to " +
site.toString());
}
Class Room (2)
...
MapSite getSide(Direction d){
MapSite result = null;
if (d == Direction.North){
result = _northSide;
} else if (d == Direction.South){
result = _southSide;
} else if (d == Direction.East){
result = _eastSide;
} else if (d == Direction.West){
result = _westSide;
}
return result;
}
East West
if(kit.equals("a")){
public class Client{
pf=new ConcreteFactory1();
public static void main(String args[]){
}
AbstractFactory pf=getFactory("a"); //
else if(kit.equals("b")){
AbstractProductA product=pf.createProductA();
pf=new ConcreteFactory2();
//more function calls on product }
}
}
return pf;
class MazeFactory {
public Maze makeMaze(){ return new Maze(); }
public Wall makeWall(){ return new Wall(); }
public Room makeRoom(){ return new Room(); }
public Door makeDoor(Room r1, Room r2){
return new Door(r1,r2);
}
}
MazeGame
class MazeGame {
public Maze createMaze(MazeFactory factory){
Maze aMaze = factory.makeMaze();
class MazeGame {
public Maze createMaze(){
Room r1 = factory.makeRoom();
Maze aMaze = new Maze();
Room r2 = factory.makeRoom(); Room r1 = new Room();
Door theDoor = factory.makeDoor(r1,r2);
Room r2 = new Room();
Door theDoor = new Door(r1,r2);
aMaze.addRoom(r1); aMaze.addRoom(r2);
aMaze.addRoom(r1); aMaze.addRoom(r2);
r1.setSide(Direction.North, factory.makeWall());
r1.setSide(Direction.North, new Wall());
r1.setSide(Direction.East, theDoor);
r1.setSide(Direction.East, theDoor);
r1.setSide(Direction.South, new Wall());
r1.setSide(Direction.South, factory.makeWall());
r1.setSide(Direction.West, new Wall());
r1.setSide(Direction.West, factory.makeWall());
r2.setSide(Direction.North, new Wall());
r2.setSide(Direction.East, new Wall());
r2.setSide(Direction.North, factory.makeWall());
r2.setSide(Direction.South, new Wall());
r2.setSide(Direction.East, factory.makeWall());
r2.setSide(Direction.West, theDoor);
return aMaze;
r2.setSide(Direction.South, factory.makeWall());
}
r2.setSide(Direction.West, theDoor);
}
return aMaze;
}
}
Updated Driver
public class Main {
public static void main(String[] args){
MazeFactory factory = new MazeFactory();
MazeGame game = new MazeGame();
game.createMaze(factory);
}
}
in general:
downcasting may be needed when you want to access
methods/fields in ConcreteProducts
If EnchantedRoom had to access a subclass-specific member of EnchantedWall then it would
have to cast a reference to its walls fromWall to EnchantedWall downcast is required.
useful for situations where you create many instances of the same
product, but where you want to be able to vary the product
often used together with the Singleton pattern (concrete factory)
Disadvantages:
Supporting a new kind of products (e.g., new widget) is difficult –
requires extending the interface.
Client does not know the kind of product that is produced. Might require
downcaasting.
Factory Method
alternative approach:
define factory methods in MazeGame for creating Maze/Room/Wall/Door
objects
update MazeGame.createMaze() to use factory methods
benefit:
allows one to create specialized versions of the game by creating subclasses
of MazeGame
override some or all of MazeGame’s factory methods
Factory Method
The client expects an implementation of an interface or abstract
class, but doesn't know exactly what concrete class the factory will
return.
Abstract Factory
Here, there is one more level of abstraction.
The client does not even know what factory it's going to use.
First, it gets a Factory and then it calls a Factory method.
Advantages:
Client code is free from application specific classes.
Provides hooks for further subclassing or versioning.
Disadvantage:
Clients must subclass the creator just to create a concrete
product object.
private MazeFactory(){ }
I wrote the article after seeing at least two dozen instances of the following
code deep within the server of the project I was working on:
MySingletonObject mySingletonObject =
MySingletonObject.getInstance();
MyApp.singletonObject = mySingletonObject;
The rest of the programmers were encouraged to use the singleton objects
through MyApp rather than directly. In that case, why the hell are they
singletons?!
I've never used a singleton to make sure there was only one of something.
Singletons usually are used to provide a single point of access to a global
service.
I always make the singleton separate from the class itself so the class can be used
any way you want.
The singleton can then use the class. The singleton also doesn't have to instantiate
the object. It just has to provide access to the object.
The object returned can best be set by any means necessary. That's more like the
different, but related, FactoryPattern.
To decide whether a class is truly a singleton, you must ask yourself some
questions.
Will every application use this class exactly the same way? (exactly is the key
word)
Will every application ever need only one instance of this class? (ever and one
are the key words)
Should the clients of this class be unaware of the application they are part
of?
If you answer yes to all three questions, then you've found a singleton.
The key points here are that a class is only a singleton if all applications treat it
exactly the same and if its clients can use the class without an application
context.
The problem:
The number of possible conversions is
open-ended. It should be easy to add a
new conversion without modifying the reader.
Software Engineering, 2012 Design Patterns – Creational patterns 64
Builder: Solution
Configure the RTFReader class with a TextConverter object that
converts RTF to another textual representation.
The RTFReader parses the RTF document,
When it recognizes an RTF token t
calls aTextConverter on t.
TextConverter responsibilities:
perform data conversion.
represent the token in a particular format.
Create and assemble a complex object.
Hide this process.
interface MazeBuilder {
public void buildMaze();
public Room buildRoom();
public void buildDoor(Room from, Direction side1,
Room to, Direction side2);
public Maze getMaze();
}
return builder.getMaze();
r2.setSide(Direction.South, new Wall());
r2.setSide(Direction.West, theDoor);
} return aMaze;
} }
Software Engineering, 2012 Design Patterns – Creational}patterns 72
Class StandardMazeBuilder (1)
class StandardMazeBuilder implements MazeBuilder {
public void buildMaze(){
_currentMaze = new Maze();
}
public Room buildRoom(){
Room r = new Room();
_currentMaze.addRoom(r);
r.setSide(Direction.North,new Wall());
r.setSide(Direction.South,new Wall());
r.setSide(Direction.East, new Wall());
r.setSide(Direction.West, new Wall());
return r;
} ...
Client only knows the Director (the createMaze() method) and the
ConcreteBuilder (StandardMazeBuilder) s/he wants to use
no details about how to construct Products
no details of Product representation
1. create()
2. createMaze()
1. create ()
1.1 create ()
:Driver g:MazeGame
1. create()
2. createMaze()
1. create()
2. create ()
3. createMaze (b)
1. create ()
2. create ()
3. create ()
4. create (wp,wp)
5. create (mp,wp,rp,dp)
6. createMaze (f)