Design patterns IV : Creational Patterns · Design patterns IV : Creational Patterns J.Serrat...

31
Design patterns IV : Creational Patterns J.Serrat 102759 Software Design October 20, 2013 Index 1 Singleton 2 Factory method 3 Abstract factory 4 Prototype 5 Builder

Transcript of Design patterns IV : Creational Patterns · Design patterns IV : Creational Patterns J.Serrat...

Design patterns IV : Creational Patterns

J.Serrat

102759 Software Design

October 20, 2013

Index

1 Singleton

2 Factory method

3 Abstract factory

4 Prototype

5 Builder

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Overview

Behavioural patterns characterize the ways in which classes orobjects interact and distribute responsibility

Structural patterns deal with the composition of classes orobjects to form larger structures (composite, bridge) or torealize new functionality (adapter . . . )

Creational patterns concern the process of object creation

3 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

Head-first design patterns. E. Freeman et al. O’Reilly, 2004

4 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

Motivation

sometimes in a design there are classes for which at most anobject must be instantiated

this object is often used by other objects/classes throughoutall our design

think of a printer spooler, a calculation, a clock, a userinterface dialog, the company CEO, a device driver. . .

it would wrong to instantiate more than one such objects,according to the requirements

5 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

Can you do that with a global variable, like a static one in Java ?

public class HPDeskJet1050Driver extends PrinterDriver {

public HPDeskJet1050() { //... }

public void initPrinter() { //... }

public void stopPrinter() { //... }

public void print(File file) { //... }

}

static PrinterDriver printerDriver = new HPDeskJet1050Driver();

yes, but the object is created when application starts, notwhen it is needed: lazy vs eager initialization

applying Singleton pattern is explicitly declaring your intentionof uniqueness

all designers know the Singleton trick

it’s a very easy pattern to apply

6 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

Silly example from Head-first design patterns: a chocolate boiler.

7 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

public class ChocolateBoiler {

private boolean empty;

private boolean boiled;

public ChocolateBoiler() {

empty = true;

boiled = false;

}

public void fill(){

if (isEmpty()) {

// fill in the boiler

// with milk and chocolate

empty = false;

boiled = false;

}

}

public void drain() {

if (!isEmpty() && isBoiled()) {

// drain boiled milk

// and chocolate

empty = true;

}

}

public void boil() {

if (!isEmpty() && !isBoiled()) {

// bring contents to a boil

boiled = true;

}

}

public boolean isEmpty() {

return empty;

}

public boolean isBoiled() {

return boiled;

}

8 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

public class ChocolateBoiler {

private boolean empty;

private boolean boiled;

private static ChocolateBoiler uniqueInstance = null;

private ChocolateBoiler() {

empty = true;

boiled = false;

}

// lazy initialization

public static ChocolateBoiler getInstance() {

if (uniqueInstance == null) {

return new ChocolateBoiler();

} else {

return uniqueInstance;

}

}

// rest of ChocolateBoiler methods

9 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

Intent

Ensure a class only has one instance, and provide a global point ofaccess to it.

Structure

declare constructor private

public static method to return the unique instance

either initialize unique instance (eager) or defer it to first callto get instance (lazy)

10 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

11 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

12 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

13 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

14 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

15 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

16 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

public static ChocolateBoiler   getInstance() {

public static ChocolateBoiler   getInstance() {

if (uniqueInstance==null) {

if (uniqueInstance==null) {

uniqueInstance = new   ChocolateBoiler();

uniqueInstance = new   ChocolateBoiler();

return uniqueInstance;

return uniqueInstance;

null

null

null

<object1>

<object1>

<object2>

<object2>

17 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

public class ChocolateBoiler {

private boolean empty;

private boolean boiled;

private static ChocolateBoiler uniqueInstance = null;

private ChocolateBoiler() {

empty = true;

boiled = false;

}

// lazy initialization

public static synchronized ChocolateBoiler getInstance() {

if (uniqueInstance == null) {

return new ChocolateBoiler();

} else {

return uniqueInstance;

}

}

// rest of ChocolateBoiler methods

18 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

How to deal with threads ?

by adding the synchronized keyword no two threads mayenter getInstance at the same time but must wait their turn

however, this may cause overhead (100 times slower)

synchronization is only needed before settinguniqueInstance and not anymore

if performance is not an issue (or there are not multiplethreads), do nothing

if singleton object is not expensive (time, memory) to create,do eager initialization

if it is, double checked locking

19 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

public class ChocolateBoiler {

private boolean empty;

private boolean boiled;

private static ChocolateBoiler uniqueInstance

= new ChocolateBoiler();

private ChocolateBoiler() {

empty = true;

boiled = false;

}

// eager initialization

public static ChocolateBoiler getInstance() {

return uniqueInstance;

}

// rest of ChocolateBoiler methods

20 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singletonpublic class ChocolateBoiler {

private boolean empty;

private boolean boiled;

private static volatile ChocolateBoiler uniqueInstance = null;

// volatile ensures multiple threads handle the attribute

// correctly when it is being initialized to the instance

private ChocolateBoiler() {

empty = true; boiled = false;

}

// double checked locking

public static ChocolateBoiler getInstance() {

if (uniqueInstance == null) {

synchronized ( ChocolateBoiler.class ) {

// therefore, only synchronize the first time

if (uniqueInstance == null) { // check again

uniqueInstance = new ChocolateBoiler();

}

}

return uniqueInstance;

}

21 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

How to deal with inheritance ?

singleton as an abstract class complicates the implementation,better avoid it

in Java, another way to create objects is to override clone()

and implement interface Cloneable

making the class final prevents cloning. Since Singleton isinherited directly from Object, the clone() method remainsprotected so it cannot be used

22 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Singleton

How to deal with inheritance ?

just in case Singleton class could inherit from another classthat has overriden clone(),

class MySingleton implements Cloneable {

@Override

public Object clone() throws CloneNotSupportedException {

throw new CloneNotSupportedException();

// could return the instance but it seems misleading

// for the client code to do so from a clone = ’give

// a copy’ method

}

//...

}

23 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

Motivating example: an old example of Composite

build a maze for a computer game, where the player has tofind the way out

maze is made of rooms, a room knows its neighbours: anotherroom, a wall, or a door to another room

you can enter a room, door (changes room if open) and evena wall (if given the power to do so, change room)

now we focus on the creation of a maze, not representation(Composite) or players (State)

24 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

room r2 room r1

theDoor

wall

25 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

26 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory methodclass Room implements MapSite {

ArrayList<MapSite> sides = new ArrayList<MapSite>();

public setSide(int direction, MapSite ms) {

int index;

switch (direction) {

case North: index = 0; break;

case East: index = 1; break;

case South: index = 2; break;

case West: index = 3; break;

default: assert false;

sides.toArray()[index] = ms;

}

public Room(MapSite up, MapSite right,

MapSite down, Mapsite left) {

setSide(North, up);

setSide(East, right);

setSide(South, down);

setSide(West, left);

}

}

27 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

class MazeGame {

public Maze CreateMaze() {

Maze aMaze = new Maze();

Door theDoor = new Door();

Room r1 = new Room(new Wall(), new Wall(), new Wall(),

theDoor);

Room r2 = new Room(new Wall(), theDoor, new Wall(),

new Wall());

theDoor.setRooms(r1, r2);

aMaze.addRoom(r1);

aMaze.addRoom(r2);

return aMaze;

}

//...

}

28 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

The problem with CreateMaze() is its inflexibility: ithard-codes the maze layout and component classes.

Changing the layout and/or component classes meanschanging this method, either by overriding it—reimplementing the whole thing— or by changing parts of it—error-prone and doesn’t promote reuse.

The Factory Method and later Abstract Factory will make iteasy to change the classes that define the components of amaze.

29 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

Want to reuse an existing maze layout for a new gamecontaining enchanted mazes

an enchanted maze has new kinds of components:

DoorNeedingSpell, a door that can be locked and openedsubsequently only with a spellEnchantedRoom, a room with magic keys or spells.

How to change CreateMaze easily so that it creates a mazewith the same layout but with these new classes of room anddoor?

Call, instead of constructors, factory methods which createthe right class of objects depending on the factory subclassthey belong to.

30 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

31 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

With factory method

abstract class MazeGame {

public Maze createMaze() {

Maze aMaze = new Maze();

Door theDoor = makeDoor();

Room r1 = makeRoom(makeWall(), makeWall(), makeWall(),

theDoor);

Room r2 = makeRoom(makeWall(), theDoor, makeWall(),

makeWall());

theDoor.setRooms(r1, r2);

aMaze.addRoom(r1); aMaze.addRoom(r2);

return aMaze;

}

public abstract Room makeRoom(MapSite up, MapSite right,

MapSite down, MapSite left);

public abstract Door makeDoor();

public abstract Wall makeWall();

} //...

MazeGame game = new EnchantedMazeGame(); // new NormalMazeGame();

Maze maze = game.createMaze();32 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

Original code

class MazeGame {

public Maze createMaze() {

Maze aMaze = new Maze();

Door theDoor = new Door();

Room r1 = new Room(new Wall(), new Wall(), new Wall(),

theDoor);

Room r2 = new Room(new Wall(), theDoor, new Wall(),

new Wall());

theDoor.setRooms(r1, r2);

aMaze.addRoom(r1);

aMaze.addRoom(r2);

return aMaze;

}

}

//...

MazeGame game = new MazeGame();

Maze maze = game.createMaze();

33 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

Intent

Define an interface for creating an object, but let subclasses decidewhich class to instantiate. Factory Method lets a class deferinstantiation to subclasses.

Applicability

a class can’t anticipate the class of objects it must create

a class wants its subclasses to specify the objects it creates

classes delegate responsibility to one of several helpersubclasses, and you want to localize the knowledge of whichhelper subclass is the delegate

34 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

Structure

35 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

Motivating example: continuing the maze creation problem,

NormalRoom, NormalDoor and EnchantedRoom,DoorNeedingSpell is not the only difference between mazesof NormalMazeGame and EnchantedMazeGame

now maybe even walls are different

for each type of maze there is a different family of mapsites

the maze of a game is made either of [exclusive or] normalsites or enchanted sites or . . . whatever sites

36 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

37 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

38 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

With Abstract factory

class MazeGame {

public Maze createMaze(MazeFactory factory) {

Maze aMaze = new Maze();

Door theDoor = factory.makeDoor();

Room r1 = factory.makeRoom(factory.makeWall(),

factory.makeWall(), factory.makeWall(), theDoor,);

Room r2 = factory.makeRoom(factory.makeWall(), theDoor,

factory.makeWall(), factory.makeWall());

theDoor.setRooms(r1, r2);

return aMaze;

}

} //...

MazeFactory factory = new EnchantedMazeFactory();

// MazeFactory factory = new NormalMazeFactory();

MazeGame game = new MazeGame();

Maze maze = game.createMaze(factory);

39 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Factory method

With Factory Method

abstract class MazeGame {

public Maze createMaze() {

Maze aMaze = new Maze();

Door theDoor = makeDoor();

Room r1 = makeRoom(makeWall(), makeWall(), makeWall(),

theDoor);

Room r2 = makeRoom(makeWall(), theDoor, makeWall(),

makeWall());

theDoor.setRooms(r1, r2);

aMaze.addRoom(r1); aMaze.addRoom(r2);

return aMaze;

}

public abstract Room makeRoom(MapSite up, MapSite right,

MapSite down, MapSite left);

public abstract Door makeDoor();

public abstract Wall makeWall();

} //...

MazeGame game = new EnchantedMazeGame(); // new NormalMazeGame();

Maze maze = game.createMaze();40 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

Intent

Provide an interface for creating families of related or dependentobjects without specifying their concrete classes.

Applicability

a system should be independent of how its products arecreated, composed, and represented

a system should be configured with one of multiple families ofproducts

a family of related product objects is designed to be usedtogether, and you need to enforce this constraint

you want to provide a class library of products, and you wantto reveal just their interfaces, not their implementations.

41 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

Structure

42 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

Consequences

Clients manipulate class instances through their abstractinterfaces, product class names are isolated in theimplementation of the concrete factory, do not appear inclient code.

Makes exchanging product families easy: the class of aconcrete factory appears only once in an application, whereit’s instantiated.

Promotes consistency among products: using objects fromonly one family at a time

43 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

Consequences

Supporting new kinds of products is difficult: theAbstractFactory interface fixes the set of products that can becreated

Relations to other patterns:

Concrete factories are often Singleton

Each class of concrete Product is made at a Factory MethodmakeProduct

If many families of products exist, factories may prefer toclone a product of some family instead of invoking constructor(Prototype)

44 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

A real example of abstract factory: JDBC connection and queryexecution

45 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

A real example of abstract factory: JDBC connection and queryexecution

46 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Abstract factory

String dbasePrefix = "jdbc:";

String dbase = "mysql://localhost:3306/";

// String dbase = "derby:testdb";

String dbaseName = dbasePrefix + dbase;

try {

Class.forName(driverName);

// causes the class to be dynamically loaded (at runtime) and

all its static block executed

connection = DriverManager.getConnection(dbaseName, username,

password);

} catch (Exception e) { // dbase not found?

System.err.println("can’t connect to " + dbaseName + "

because " + e);

connection = DriverManager.getConnection(dbaseName +

";create=true");

}

statement = connection.createStatement();

statement.execute("select * from CUSTOMER");

47 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Motivating example:

same maze creation as before

want to avoid making a factory per type of game, in parallelto mapsites hierarchies

a simpler solution is give to a factory the list of mapsiteobjects of the right subclass

the factory object copies (clones) them to create the maze

48 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

class MazePrototypeFactory {

private Wall prototypeWall;

private Room prototypeRoom;

private Door prototypeDoor;

public Maze MazePrototypeFactory(Wall wall, Room room,

Door door) {

prototypeWall = wall; prototypeRoom = room;

prototypeDoor = door;

}

private Wall makeWall() { return prototypeWall.clone(); }

private Door makeDoor() { return prototypeDoor.clone(); }

private Room makeRoom(MapSite up, MapSite right,

MapSite down, MapSite left) {

Room newRoom = room.clone();

newRoom.initialize(up, right, down, left);

return newRoom;

}

}

49 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

MazePrototypeFactory factory = new MazePrototypeFactory(

new Wall(), new EnchantedRoom(), new DoorNeedingSpell() );

MazeGame game = new MazeGame();

Maze maze = game.createMaze(factory);

Like in Abstract Factory,

class MazeGame {

public Maze createMaze(MazeFactory factory) {

Maze aMaze = new Maze();

Door theDoor = factory.makeDoor();

Room r1 = factory.makeRoom(factory.makeWall(),

factory.makeWall(), factory.makeWall(), theDoor,);

Room r2 = factory.makeRoom(factory.makeWall(), theDoor,

factory.makeWall(), factory.makeWall());

theDoor.setRooms(r1, r2);

return aMaze;

}

}

50 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Second example: traffic simulation (from GRASP patterns,creation expert)

Traffic simulator, with entries, exits and different types ofvehicles.Each type differs in a range of possible values for vehiclelength and maximum speed.When a vehicle is created, these two parameters get a randomvalue within their range.

51 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Entries E1, E2...throw vehicles to lanes, if traffic permits so.

Each entry must create each type of vehicle with its ownprogrammed frequency, like:

Entry Cars Trucks Long trucks

E1 80% 20% 0%E2 50% 30% 20%. . . . . . . . . . . .

52 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Who is prototype factory ? Who are the products ?

53 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Frequencies is aprototype factory whichsupplies vehicles to eachentry. Each Frequencies

object has a list of vehicleprototypes plus percentfrequency,PrototipVehicle.

54 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Client instantiates a Frequencies and assigns it to a Entrada.

55 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Entrada gets some type of vehicle from its particular vehiclefactory.

56 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Not all Car or Track objects are equal: their constructor gets arandom max speed, length etc. within the class range.

57 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Not all Car or Track objects are equal: their constructor gets arandom max speed, length etc. within the class range.Method clona() returns a new object of the same type asprototype, but not exactly equal.

58 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Intent

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.

Applicability

A system should be independent of how its products are created,composed, and represented; and

the classes to instantiate are specified at run-time

to avoid building a class hierarchy of factories that parallelsthe class hierarchy of products

instances of a class can have one of only a few differentcombinations of state: better create a number of prototypeseach in a state than create and bring to state manually

59 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Prototype

Structure

60 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

Builder

Exercise

61 / 62

Overview Singleton Factory method Abstract factory Prototype Builder You should know. . .

You should know

intent and structure of each pattern

similarity and differences of Factory Method, AbstractFactory: a unique or several product families

similarity and differences of Singleton and Prototype: providesame versus equal object

what each pattern encapsulates

Pattern Aspects that vary

Singleton the sole instance of a classFactory Method subclass of object that is instantiatedAbstract Factory families of product objectsPrototype class of object that is instantiated

62 / 62