40
1 1. Introduction 2. Factory Method 3. Abstract Factory 4. Prototype 5. Builder 6. Singleton

1 1.Introduction 2.Factory Method 3.Abstract Factory 4.Prototype 5.Builder 6.Singleton

Embed Size (px)

Citation preview

1

1. Introduction2. Factory Method3. Abstract Factory4. Prototype5. Builder6. Singleton

2

The Gang Of Four catalogue

Purpose

Sco

pe

Class

Object

Creational Structural Behavioral

Factory Method

Abstract Factory

Builder

Prototype

Singleton

Adapter

Adapter

Bridge

Composite

Decorator

Façade

Flyweight

Proxy

Interpreter

Template Method

Chain of resp.

Command

Iterator

Mediator

Memento

Observer

State

Strategy

Visitor

3

Creational Patterns

Common objective : - abstract object creation process (how, when, by whom)- avoid hard coding concrete types in client code

Fundamental problem : “weaknesses of constructors”• fixed return type (= DYNAMIC type)• not inherited -> no polymorphism possible

Solutions :- use inheritance to decide run time type

(class creational – factory method)- delegate creation process to object –

run time types depend on object type and behavior(object creational)

4

Creational PatternsNo constructor polymorphism

Desired dependency

Unwanted dependency

Solutions :Factory methodAbstract FactoryPrototype

//…Common c = new A();Common d = new B();// …

5

Motivation• support pluggable GUI look and feel• abstract look and feel code from client (to promote cross-platform portability)

BUT :• client must hardcode concrete object types

(can not program to top level classes !)• product families can get mixed !

6

Motivation

class Client {

public Client() {// …Button b = new XPButton();Window w = new XPWindow();Button c = new AppleButton();// …

}}

Constructor weaknesses :• fixed return type (= DYNAMIC type)• not inherited -> no polymorphism possible

Solution : create constructor-like method (the “factory method”)

7

The solutionA Factory Method

8

The solutionabstract class Client {

private Button b,c;

private Window w;

public Client() {

// …

b = createButton();

w = createWindow();

c = createButton();

// …

}

public abstract Button createButton(); // factory method

public abstract Window createWindow(); // factory method

}

class AppleClient extends Client {

public AppleClient() {super();}

public Window createWindow() {return new AppleWindow();}

public Button createButton() {return new AppleButton();}

}

class Test {

public static void main(String[] args) {

Client c=new AppleClient();

}

}

9

The general solution

return new ConcreteProduct();

10

Example : A bike raceclass Bicycle {

protected String trademark;

protected int ID;

public Bicycle(String s,int i) {trademark=s;ID=i;}

public String toString() {

return ""+trademark+" : "+ID;

}

}

class StandardBicycle extends Bicycle {

public StandardBicycle(String t,int i) {super(t,i);}

public String toString() {

return "Standard Bike : "+super.toString();

}

}

class Tandem extends Bicycle {

public Tandem(String t,int i) {super(t,i);}

public String toString() {

return "Tandem : "+super.toString();

}

}

11

Example : A bike raceclass Participant {

protected String name;

public Participant(String s) {name=s;}

public String toString() {

return name;

}

}

class StandardParticipant extends Participant{

public StandardParticipant(String s) {super(s);}

public String toString() {

return "Standard Participant : "+super.toString();

}

}

class TandemParticipant extends Participant{

public TandemParticipant(String s) {super(s);}

public String toString() {

return "Tandem Participant : "+super.toString();

}

}

12

Example : A bike raceabstract class Race {

Bicycle[] b;

Participant[] p;

public Race(String[] tm,String[] n) {

b=new Bicycle[tm.length];

p=new Participant[tm.length];

for(int i=0;i<b.length;i++) {

b[i]=createBicycle(tm[i],i);

p[i]=createParticipant(n[i]);

}

}

public String toString() {

String r="The race :\n";

for(int i=0;i<b.length;i++)

r+="\t"+b[i]+" -> "+p[i]+"\n";

return r;

}

public Participant doRace() {

return p[(int)(Math.random()*(b.length))];

}

public abstract Bicycle createBicycle(String s,int i);

public abstract Participant createParticipant(String s);

}

NO CONSTRUCTORS HERE !

Factory methods

13

Example : A bike raceclass StandardRace extends Race {

public StandardRace(String[] tm,String[] n) {super(tm,n);}

public Bicycle createBicycle(String s,int i) {

return new StandardBicycle(s,i);

}

public Participant createParticipant(String s) {

return new StandardParticipant(s);

}

}

class TandemRace extends Race {

public TandemRace(String[] tm,String[] n) {super(tm,n);}

public Bicycle createBicycle(String s,int i) {

return new Tandem(s,i);

}

public Participant createParticipant(String s) {

return new TandemParticipant(s);

}

}

14

Example : A bike raceclass Test {

public static void main(String[] args) {

String[] tm={"Eddy M.","Bike Inc.","Wheels2Wheels","Eddy M."};

String[] n={"John","Mary","Eddy","Fred"};

Race r=new TandemRace(tm,n);

// or : Race r=new StandardRace(tm,n);

System.out.println(r);

System.out.println("START ...");

System.out.println("The winner is : "+r.doRace());

}

}

15

Notes

• when difficult to anticipate what type of objects to create

• when subclass must specify object type to create

Applicability

Consequences

• allows for hooks in the application through subclassing

• allows to connect parallel class hierarchies

Factory methods are often used in• other creational patterns• Template Method pattern

16

The solutionAn Abstract Factory

17

The solution

class Client {GUIFactory f;public Cient(GUIFactory ff) {

f=ff;// …Button b = f.createButton();Window w = f.createWindow();Button c = f.createButton();// do something useful

}}

class Test {public static void main(String[] args) {

Client c=new Client(new XPGUIFactory());}

} • version for XP platform• can be changed (check at runtime which factories are available)

18

The general solution

19

Example : A bike raceinterface RaceFactory {

Bicycle createBicycle(String s,int ID);

Participant createParticipant(String s);

}

class StandardRaceFactory implements RaceFactory {

public Bicycle createBicycle(String s,int ID) {

return new StandardBicycle(s,ID);

}

public Participant createParticipant(String s) {

return new StandardParticipant(s);

}

}

class TandemRaceFactory implements RaceFactory {

public Bicycle createBicycle(String s,int ID) {

return new Tandem(s,ID);

}

public Participant createParticipant(String s) {

return new TandemParticipant(s);

}

}

20

Example : A bike raceclass Race {

RaceFactory f;

Bicycle[] b;

Participant[] p;

public Race(RaceFactory ff,String[] tm,String[] n) {

f=ff;

b=new Bicycle[tm.length];

p=new Participant[tm.length];

for(int i=0;i<b.length;i++) {

b[i]=f.createBicycle(tm[i],i);

p[i]=f.createParticipant(n[i]);

}

}

public String toString() {

String r="The race :\n";

for(int i=0;i<b.length;i++)

r+="\t"+b[i]+" -> "+p[i]+"\n";

return r;

}

public Participant doRace() {

return p[(int)(Math.random()*(b.length))];

}

}

21

Example : A bike race

class Test {

public static void main(String[] args) {

RaceFactory f=new TandemRaceFactory();

// or : RaceFactory f=new StandardRaceFactory();

String[] tm={"Eddy M.","Bike Inc.","Wheels2Wheels","Eddy M."};

String[] n={"John","Mary","Eddy","Fred"};

Race r=new Race(f,tm,n);

System.out.println(r);

System.out.println("START ...");

System.out.println("The winner is : "+r.doRace());

}

}

22

Notes

• when independency of product creation, composition and representation is needed

• when system should be configured with different product families

• when enforcing constraints on using only products in family

Applicability

Consequences

• concrete product classes shielded from client application code

• easy to change between product families, and to enforce consistency

• difficult to add new products

Creation of abstract factory object itself often implemented as a Singleton !

23

The solutionPrototyping

24

The solutionclass Client {

Button protoButton;Window protoWindow;Button b,c;Window w;public Cient(Button bb,Window ww) {

protoButton=bb;protoWindow=ww;// …b = protoButton.clone();w = protoWindow.clone();c = protoButton.clone();// do something useful

}}class Test {

public static void main(String[] args) {Client c=new Client(new XPWindow(), new AppleButton());

}}

25

The general solution

26

Example : A bike raceclass Bicycle {

protected String trademark;

protected int ID;

public Bicycle(String s,int i) {trademark=s;ID=i;}

public String toString() {return ""+trademark+" : "+ID;}

public Bicycle mclone() {return new Bicycle(trademark,ID);}

public void setTrademark(String tm) {trademark=tm;}

public void setID(int i) {ID=i;}

}

class StandardBicycle extends Bicycle {

public StandardBicycle(String t,int i) {super(t,i);}

public String toString() {return "Standard Bike : "+super.toString();}

public Bicycle mclone() {return new StandardBicycle(trademark,ID);}

}

class Tandem extends Bicycle {

public Tandem(String t,int i) {super(t,i);}

public String toString() {return "Tandem : "+super.toString();}

public Bicycle mclone() {return new Tandem(trademark,ID);}

}

27

Example : A bike raceclass Participant {

protected String name;

public Participant(String s) {name=s;}

public String toString() {return name;}

public Participant mclone() {return new Participant(name);}

public void setName(String s) {name=s;}

}

class StandardParticipant extends Participant{

public StandardParticipant(String s) {super(s);}

public String toString() {return "Standard Participant : "+super.toString();}

public Participant mclone() {return new StandardParticipant(name);}

}

class TandemParticipant extends Participant{

protected String second;

public TandemParticipant(String s1,String s2) {super(s1);second=s2;}

public String toString() {

return "Tandem Participant : "+super.toString()+" + "+second;

}

public void setSecond(String s) {second=s;}

public Participant mclone() {return new TandemParticipant(name,second);}

}

28

Example : A bike raceclass Race {

private Bicycle[] b;

private Participant[] p;

private Bicycle pB;

private Participant pP;public Race(Bicycle bb,Participant pp,String[] tm,String[] n) {

pB=bb;

pP=pp;

b=new Bicycle[tm.length];

p=new Participant[tm.length];

for(int i=0;i<b.length;i++) {

b[i]=pB.mclone();b[i].setTrademark(tm[i]);b[i].setID(i);

p[i]=pP.mclone();p[i].setName(n[i]);

// can not set state for tandem participant !

}

}

public String toString() {

String r="The race :\n";

for(int i=0;i<b.length;i++)

r+="\t"+b[i]+" -> "+p[i]+"\n";

return r;

}

public Participant doRace() {

return p[(int)(Math.random()*(b.length))];

}

}

29

Example : A bike raceclass Test {

public static void main(String[] args) {

String[] tm={"Eddy M.","Bike Inc.","Wheels2Wheels","Eddy M."};

String[] n={"John","Mary","Eddy","Fred"};

// Race r=new Race(new StandardBicycle("Dummy",0),new StandardParticipant("Dummy"),tm,n);

Race r=new Race(new Tandem("Dummy",0),new TandemParticipant("X","Y"),tm,n);

System.out.println(r);

System.out.println("START ...");

System.out.println("The winner is : "+r.doRace());

}

} The race : Tandem : Eddy M. : 0 -> Tandem Participant : John + Y Tandem : Bike Inc. : 1 -> Tandem Participant : Mary + Y Tandem : Wheels2Wheels : 2 -> Tandem Participant : Eddy + Y Tandem : Eddy M. : 3 -> Tandem Participant : Fred + Y

START ...The winner is : Tandem Participant : Eddy + Y

30

Java cloningJAVA • root type Object declares : public Object clone() for copying purposes …

• Java approach : - override clone() method - requires DOWNCAST to actual type !

class Tandem extends Bicycle {

public Tandem(String t,int i) {super(t,i);}

public String toString() {return "Tandem : "+super.toString(); }

public Object clone() {return new Tandem(trademark,ID);}

}

class Race {

private Bicycle[] b;private Participant[] p;

private Bicycle pB;private Participant pP;

public Race(Bicycle bb,Participant pp,String[] tm,String[] n) {

pB=bb;pP=pp;

b=new Bicycle[tm.length];p=new Participant[tm.length];

for(int i=0;i<b.length;i++) {

b[i]=(Bicycle)(pB.clone());b[i].setTrademark(tm[i]);b[i].setID(i);

p[i]=(Participant)(pP.clone());p[i].setName(n[i]); }

} //…

}

31

Notes

• run-time specification of classes (e.g. dynamic loading application)

• avoid to construct factory hierarchy

• primarily when not too much variation in state info is required

Applicability

Implementation issues

• clone() should implement a deep copy (to be safe)

• a prototype manager can be used to hold all possible prototypes

• factory object (in Abstract Factory & Builder patterns) can be configured using prototypes

32

The solutionA Builder Supposed to be (very)

complex…

33

The solutionabstract class Client {

GUI g;

public Client(Builder bb) {

director=new Director(bb);

director.construct();

g=bb.getResult();

// …

}

}

class Director {

private Builder b;

public Director(Builder bb) {b=bb;}

public void construct() {

b.buildButton();

b.buildWindow();

//…

}

}

class Test {

public static void main(String[] args) {

Client c=new AppleClient(new AppleBuilder());

}

}

34

The general solution

35

Example : A bike raceclass NMDirector {

private int n;

private int m;

private Builder b;

public NMDirector(Builder bb,int nn,int mm) {

b=bb;n=nn;m=mm;

}

public void construct() {

b.initPartX(n);

b.initPartY(m);

for(int i=0;i<n;i++) b.buildPartX(i);

for(int i=0;i<m;i++) b.buildPartY(i);

}

}

abstract class Builder {

abstract void buildPartX(int i);

abstract void buildPartY(int i);

abstract void initPartX(int n);

abstract void initPartY(int n);

}

36

Example : A bike raceclass StandardRaceBuilder extends Builder {

private Race r=new Race();

private String[] tm,n;

public StandardRaceBuilder(String[] trade,String[] name) {

tm=trade;n=name;

}

public void initPartX(int n) {r.setBicycleSize(n);}

public void initPartY(int n) {r.setParticipantSize(n);}

public void buildPartX(int i) {r.setBicycle(new StandardBicycle(tm[i],i),i);}

public void buildPartY(int i) {r.setParticipant(new StandardParticipant(n[i]),i);}

public Race getResult() {return r;}

}

class TandemRaceBuilder extends Builder {

private Race r=new Race();

private String[] tm,n;

public TandemRaceBuilder(String[] trade,String[] name) {

tm=trade;n=name;

}

public void initPartX(int n) {r.setBicycleSize(n);}

public void initPartY(int n) {r.setParticipantSize(n);}

public void buildPartX(int i) {r.setBicycle(new Tandem(tm[i],i),i);}

public void buildPartY(int i) {r.setParticipant(new TandemParticipant(n[i]),i);}

public Race getResult() {return r;}

}

37

Example : A bike raceclass Race {

Bicycle[] b;Participant[] p;

public String toString() {

String r="The race :\n";

for(int i=0;i<b.length;i++) r+="\t"+b[i]+" -> "+p[i]+"\n";

return r;

}

public Participant doRace() {return p[(int)(Math.random()*p.length)];}

public void setBicycleSize(int n) {b=new Bicycle[n];}

public void setParticipantSize(int n) {p=new Participant[n];}

public void setBicycle(Bicycle bike,int i) {b[i]=bike;}

public void setParticipant(Participant part,int i) {p[i]=part;}

}

class Test {

public static void main(String[] args) {

String[] tm={"Eddy M.","Bike Inc.","Wheels2Wheels","Eddy M."};

String[] n={"John","Mary","Eddy","Fred"};

//StandardRaceBuilder b=new StandardRaceBuilder(tm,n);

TandemRaceBuilder b=new TandemRaceBuilder(tm,n);

NMDirector d=new NMDirector(b,tm.length,n.length);

d.construct();

Race r=b.getResult();

System.out.println(r);System.out.println("START ...");

System.out.println("The winner is : "+r.doRace());

}

}

38

Example : A bike raceclass CountingBuilder extends Builder {

private int b;

private int p;

private String[] tm,n;

public CountingBuilder(String[] trade,String[] name) {

tm=trade;n=name;

}

public void initPartX(int n) {b=0;}

public void initPartY(int n) {p=0;}

public void buildPartX(int i) {b++;}

public void buildPartY(int i) {p++;}

public int getResult() {return (b+p);};

}

class Test {

public static void main(String[] args) {

String[] tm={"Eddy M.","Bike Inc.","Wheels2Wheels","Eddy M."};

String[] n={"John","Mary","Eddy","Fred"};

CountingBuilder c=new CountingBuilder(tm,n);

NMDirector dc=new NMDirector(c,tm.length,n.length);

dc.construct();

System.out.println("The result is : "+c.getResult());

}

}

39

Notes

• algorithm for creating complex object independent of the individual parts (typical application : parsers)

• different representations of same object to be supported by the construction process

Applicability

Main usage

• parsing (XML), formatting, compilers

40

Singleton

• see chapter on “OOD”