creation al design patterns

42
Creation Creation al Design al Design Patterns Patterns Yaodong Bi Yaodong Bi March 27, 2022 March 27, 2022

Upload: joel-garner

Post on 02-Jan-2016

35 views

Category:

Documents


0 download

DESCRIPTION

Creation al Design Patterns. Yaodong Bi November 3, 2014. Creational design patterns. Factory Abstract Factory Prototype Singleton Builder. Factory. Problem The client needs to create an object of a subclass, but it does not know the subclass until runtime. Design Purpose - PowerPoint PPT Presentation

TRANSCRIPT

CreationCreational Design al Design PatternsPatterns

Yaodong BiYaodong Bi

April 20, 2023April 20, 2023

Creational design patternsCreational design patterns

FactoryFactory Abstract FactoryAbstract Factory PrototypePrototype SingletonSingleton BuilderBuilder

FactoryFactory

ProblemProblem– The client needs to create an object of a The client needs to create an object of a

subclass, but it does not know the subclass, but it does not know the subclass until runtime.subclass until runtime.

Design PurposeDesign Purpose– Create individual objects in situations Create individual objects in situations

where the constructor alone is where the constructor alone is inadequate.inadequate.

Design Pattern SummaryDesign Pattern Summary– Use methods to return required objectsUse methods to return required objects

Factory – an exampleFactory – an example

Client+useStack(Stack)

stack+push()+pop()

MyStack+push()+pop()

void useStack(Stack s) { while (condition) { stackn = new Stack(); //????? }}Stack = new MyStack();useStack(s); //?????

Factory - structureFactory - structure

Client+useProduct()

Product Creator+factoryMethod()

ConcreteCreator

+factoryMethod()

Product factorMethod() { Return new ConcreteProduct();}

ConcreteProduct

void useProduct(Creator c) { Product p = c.factoryMethod(); // use p}….Creator c = new ConcreteCreator();useProduct(c);

Factory - participantsFactory - participants

ProductProduct– defines the interface of objects the factory method creates.defines the interface of objects the factory method creates.

ConcreteProduct ConcreteProduct – implements the Product interface.implements the Product interface.

Creator Creator – declares the factory method, which returns an object of type declares the factory method, which returns an object of type

Product. Creator may also define a default implementation of Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct the factory method that returns a default ConcreteProduct object.object.

– Creator and Product could be the same classCreator and Product could be the same class ConcreteCreatorConcreteCreator

– overrides the factory method to return an instance of a overrides the factory method to return an instance of a ConcreteProduct.ConcreteProduct.

ClientClient– It depends only on Product and Creator.It depends only on Product and Creator.

CollaborationsCollaborations– Creator relies on its subclasses to define the factory method Creator relies on its subclasses to define the factory method

so that it returns an instance of the appropriate so that it returns an instance of the appropriate ConcreteProduct. ConcreteProduct.

Factory – sequence diagramFactory – sequence diagram

Client ProductCreator ConcreteCreator

ConcreteProduct

factoryMethod() factoryMethod() constructor()

op() op()

Factory – sample codeFactory – sample code

Class StackClient { void opUsingStacks(StackCreator sc) { Stack s1 = sc.createStack(); ... Stack si = sc.createStack(); ... Stack sn = sc.createStack(); }}Interface Stack { void push(Item i); Item pop();}Interface StackCreator { Stack createStack();}Class MyStack implements Stack { ...}Class YourStack implements Stack {}

Class MyStackCreator implements StackCreator { Stack createStack() { return new MyStack(); }}Class YourStackCreator implements StackCreator { Stack createStack() { return new YourStack(); }}Class ClientDriver { void main() { StackClient c = new StackClient(); StackCreator sc = new MyStackCreator(); c.opUsingStacks(sc); sc = new YourStackCreator(); c.opUsingStacks(sc); }}

Factory – commentsFactory – comments

Factory methods are necessary for the OCP Factory methods are necessary for the OCP on object creationon object creation

Factory methods make the DIP more viableFactory methods make the DIP more viable Factory Method gives subclasses a hook for Factory Method gives subclasses a hook for

providing an extended version of an objectproviding an extended version of an object Creator could be a concrete class providing a Creator could be a concrete class providing a

default implementation of Productdefault implementation of Product Creator and Product could be the same classCreator and Product could be the same class There is an advantage of using a separate There is an advantage of using a separate

creator class for the productcreator class for the product– The product and its creation are separate concernsThe product and its creation are separate concerns– When the product is very complex, the creator can When the product is very complex, the creator can

create products (even the first one) as demanded – create products (even the first one) as demanded – lazy loadinglazy loading

Abstract FactoryAbstract Factory

Design purposeDesign purpose– Provide an interface for creating Provide an interface for creating

families of related or dependent families of related or dependent objects without specifying their objects without specifying their concrete classesconcrete classes

Pattern summaryPattern summary– Capture family creation in a class Capture family creation in a class

containing a factory method for each containing a factory method for each class in the familyclass in the family

Abstract Factory – examplesAbstract Factory – examples

Word processor for different window systemsWord processor for different window systems– Word processor is designed to a set of interfaces of Word processor is designed to a set of interfaces of

graphical elementsgraphical elements– Each windows system manufactures its own set of Each windows system manufactures its own set of

button, windows, dialogs, etcbutton, windows, dialogs, etc– Each installation of the word processor is given a Each installation of the word processor is given a

windows system (concrete factory)windows system (concrete factory) Kitchen showroomKitchen showroom

– The program is designed to a common set of cabinets, The program is designed to a common set of cabinets, counters, etccounters, etc

– Each different style of kitchen furniture provide the Each different style of kitchen furniture provide the furniture in the style (classic, contemporary, etc) furniture in the style (classic, contemporary, etc)

– Each individual kitchen showroom is given a style Each individual kitchen showroom is given a style (concrete factory) (concrete factory)

GUI themesGUI themes

Abstract Factory - structureAbstract Factory - structure

Client

Factory+createProductA()+createproductB()

ProductB createProductB() { Return new ProductB1();}

ProductA

ProductA1

ProductA2

ProductB

ProductB1

ProductB2

Factory1+createProductA()+createproductB()

Factory2+createProductA()+createproductB()

ProductA createProductA() { Return new ProductA1();}

Abstract Factory – Two Abstract Factory – Two FamiliesFamilies

ProductA1

ProductA2

ProductB1

ProductB2

Factory1+createProductA()+createproductB()

Factory2+createProductA()+createproductB()

Abstract Factory - Abstract Factory - participantsparticipants

ProductA and ProductBProductA and ProductB– defines the interface of a family of objects.defines the interface of a family of objects.

ProductA1, ProductB1, ProductA2, and ProductB2 ProductA1, ProductB1, ProductA2, and ProductB2 – TTwowo separate families of product implementation. separate families of product implementation.

FactoryFactory– Defines the interface of the factory that returns the Defines the interface of the factory that returns the

productsproducts Factory1 and Factory2Factory1 and Factory2

– Concrete factories that can produce products of the Concrete factories that can produce products of the family.family.

– Factory1 produces ProductA1 and ProductB1, Factory2 Factory1 produces ProductA1 and ProductB1, Factory2 produces ProductA2 and ProductB2produces ProductA2 and ProductB2

ClientClient– It depends only on the interfaces of the family products It depends only on the interfaces of the family products

and the factory interface.and the factory interface. CollaborationsCollaborations

– The client asks a subclass of Factory to create concrete The client asks a subclass of Factory to create concrete products of ProductA and productB. products of ProductA and productB.

Abstract Factory – Two Abstract Factory – Two FamiliesFamilies

StackViaArray

StackViaListQueueViaArray

QueueViaList

DSFactoryViaArray+createStack()+createQueue)

DSFactoryViaList+createStack)+createQueue()

Data Structures Via Array

Data Structures Via List

Abstract Factory - structureAbstract Factory - structure

DataStructsClient

DSFactory+createStack()+createQueue()

Queue createQueue (){ return new QueueViaArray();}

Stack

StackViaArray

StackViaList

Queue

QueueViaArray

QueueViaList

DSFactoryViaArray+createStack()+createQueue)

DSFactoryViaList+createStack)+createQueue()

Stack createStack (){ return new StackViaArray(); }

Queue createQueue (){ return new QueueViaList();}

Stack createStack() { return new StackViaList(); }

Abstract Factory – sample Abstract Factory – sample codecode

Class DataStructsClient { DSFactory af; DataStructsClient( DSFactory af) { this.af = af; } void op() { Stack s1 = af.createStack(); Stack s2 = af.createStack(); ... Queue q = af.createQueue(); ... Tree t = af.createTree(); }}

Interface DSFactory { Stack createStack(); Queue createQueue(); Tree createTree();}

Interface Stack {...}Interface Queue {...}Interface Tree {...}

Class StackViaArray implements Stack {...}Class QueueViaArray implements Queue {...} Class TreeViaArray implements Tree {...}

Class DSFactoryViaArray implements DSFactory { Stack createStack() { return new StackViaArray(); } Queue createQueue() { return new QueueViaArray(); } Tree createTree() { return new TreeViaArray(); }}

Abstract Factory – sample Abstract Factory – sample codecode

Class ClientDriver { void main() { // Using Array-based structures DSFactory af = new DSFactoryViaArray(); DataStructsClient dsc = new DataStructsClient(af); dsc.op(); // Using list-based structures DSFactory af2 = new DSFactoryViaList(); DataStructsClient dsc2 = new DataStructsClient(af2); dsc2.op(); }}

Class StackViaList implements Stack {...}Class QueueViaList implements Queue {...} Class TreeViaList implements Tree {...}

Class DSFactoryViaList implements DSFactory { Stack createStack() { return new StackViaList(); } Queue createQueue() { return new QueueViaList(); } Tree createTree() { return new TreeViaList(); }}

Abstract Factory – Abstract Factory – commentscomments

Use the Abstract Factory when Use the Abstract Factory when a a clientclient needs needs to useto use one of multiple one of multiple familiesfamilies of products of products

It is hard to add new types of products since It is hard to add new types of products since adding a new product means adding a new adding a new product means adding a new factory method to the AbstractFactory factory method to the AbstractFactory interface and its all subclassesinterface and its all subclasses

When families of products are different When families of products are different combinations of the same set of products combinations of the same set of products and/or the # of families is large, many and/or the # of families is large, many ConcreteFactory subclasses would be ConcreteFactory subclasses would be needed. In this case, the Prototype pattern needed. In this case, the Prototype pattern may be employedmay be employed

PrototypePrototype

Design purposeDesign purpose– Create a set of almost identical Create a set of almost identical

objects whose type is determined at objects whose type is determined at runtimeruntime

Pattern summaryPattern summary– Assume that a prototype instance is Assume that a prototype instance is

known; clone it whenever a new known; clone it whenever a new instance is neededinstance is needed

Prototype – examplesPrototype – examples

Kitchen showroomKitchen showroom– A showroom may have all cabinets in A showroom may have all cabinets in

one style, counters in a different style, one style, counters in a different style, etcetc

– Instead of creating a factory for each Instead of creating a factory for each possible combination of different possible combination of different furniture in different styles, each furniture in different styles, each individual showroom is given a individual showroom is given a prototype of each type of furniture of a prototype of each type of furniture of a stylestyle

– Each prototype can clone itselfEach prototype can clone itself

Prototype - structurePrototype - structure

Client+anOperation()

Prototype+clone()+otherOperations()

Return a copy of itself

ConcreteProduct1

+clone();+otherOperations();

ConcreteProduct2

+cone();+otherOperations();

Return a copy of itself

Prototype p = prototype.clone();

prototype

Prototype - participantsPrototype - participants

PrototypePrototype– defines the interface (an operation) of defines the interface (an operation) of cloning cloning

itselfitself.. ConcreteProduct1 and ConcreteProduct2ConcreteProduct1 and ConcreteProduct2

– Concrete objects that can clone themselvesConcrete objects that can clone themselves.. ClientClient

– Obtain more objects by asking them to clone Obtain more objects by asking them to clone themselvesthemselves..

CollaborationsCollaborations– The client asks The client asks the prototype to clone itself the prototype to clone itself

for a new object of the prototypefor a new object of the prototype. .

Shallow vs. deep cloning Shallow vs. deep cloning (copying)(copying)

Client+anOperation()

:Prototype+clone()-Nested:ref

prototype ref:Nested

+op()-data

Client+anOperation()

:Prototype+clone()-Nested:ref

prototype ref:Nested

+op()-data

clone:Prototype

+clone()-Nested:ref

ref

Client+anOperation()

:Prototype+clone()-Nested:ref

prototype ref:Nested

+op()-data

clone:Prototype

+clone()-Nested:ref

ref clone:Nested+op()-data

Shallow cloning

Deep cloning

Shallow vs. deep cloningShallow vs. deep cloning

Shallow cloning: sample codeShallow cloning: sample code

Class Prototype implements Cloneable {Class Prototype implements Cloneable { private int x;private int x; private Nested ref = new Nested();private Nested ref = new Nested();

public Prototype clone() {public Prototype clone() { Prototype p = new Prototype()Prototype p = new Prototype() p.x = this.x;p.x = this.x; p.ref = this.ref; return p;return p; }}}}Class Nested { int data;int data; public void op() {}public void op() {}}}Class Client {Class Client { private Prototype prototype = private Prototype prototype = new Prototype();new Prototype(); public void op() {public void op() { Prototype clone = Prototype clone =

prototype.clone();prototype.clone(); // use clone// use clone}}

Deep cloning: sample codeDeep cloning: sample code

Class Prototype implements Cloneable Class Prototype implements Cloneable {{

private int x;private int x; private Nested ref = new Nested();private Nested ref = new Nested(); public Prototype clone() {public Prototype clone() { Prototype p = new Prototype()Prototype p = new Prototype() p.x = this.x;p.x = this.x; p.ref = this.ref.clone();p.ref = this.ref.clone(); return p;return p; }}}}Class Nested Class Nested implements Cloneable {implements Cloneable { int data;int data; public void op() {}public void op() {} public Nested clone() {public Nested clone() { Nested n = new Nested()Nested n = new Nested() n.data = this.data;n.data = this.data; return n;return n; }}}}Class Client {Class Client { // the same Client as for Shallow // the same Client as for Shallow

cloningcloning}}

Abstract Factory – Two Abstract Factory – Two FamiliesFamilies

StackViaArray

StackViaList

QueueViaArray

Data Structures Via Array

Data Structures Via List

Stack

Queue QueueViaList

Prototype – sample codePrototype – sample code

Class PrototypeClient { Stack sp; Queue qp; PrototypeClient( Stack s, Queue q) { this.s = s; this.q = q; } void op() { Stack s1 = sp.clone(); Stack s2 = sp.clone(); ... Queue q1 = qp.clone(); Queue q2 = qp.clone(); }}

Interface Queue { Queue clone(); ...}

Interface Stack { Stack clone(); ...} Class StackViaArray implements Stack { Stack clone() { StackViaArray s = new StackViaArray(); s.attr = this.attr; return s; } ...}Class StackViaList implements Stack { Stack clone() { StackViaList s = new StackViaList(); s.attr = this.attr; return s; } ...}

Prototype – sample codePrototype – sample code

Class QueueViaArray implements Queue { Queue clone() { QueueViaArray s = new QueueViaArray(); s.attr = this.attr; return s; } ...}Class QueueViaList implements Queue { Queue clone() { QueueViaList s = new QueueViaList(); s.attr = this.attr; return s; } ...}

Interface Queue { Queue clone(); ...}

Class ClientDriver { void main() { Stack s = new StackViaArray(); Queue q = new QueueViaList(); PrototypeClient pc = new PrototypeClient(s, q); pc.op(); }}

Prototype – commentsPrototype – comments

If the clone does not need to be If the clone does not need to be identical as its original, a factory identical as its original, a factory method may be usedmethod may be used

Be aware of the shallow cloning Be aware of the shallow cloning problem – to the deepest levelproblem – to the deepest level

When prototypes can be grouped When prototypes can be grouped in a small # of different in a small # of different combinations, the Abstract combinations, the Abstract Factory may be suitableFactory may be suitable

SingletonSingleton

Design purposeDesign purpose– Ensure there is exactly one instance Ensure there is exactly one instance

of a classof a class– Be able to obtain the instance from Be able to obtain the instance from

anywhere in the applicationanywhere in the application Pattern summaryPattern summary

– Make the Make the constructorconstructor of class of class private private oror protected protected, define a , define a private static private static attributeattribute of the class, define a of the class, define a public public accessoraccessor to it. to it.

Singleton – an exampleSingleton – an example

A concrete factory in the Abstract A concrete factory in the Abstract Factory pattern in most cases Factory pattern in most cases should have only one instance – should have only one instance – all objects are produced by the all objects are produced by the same factorysame factory

In JGrasp (or any IDE), we want In JGrasp (or any IDE), we want one JVM (Singleton) for all Java one JVM (Singleton) for all Java programs.programs.

Singleton - structureSingleton - structure

return soleInstance;

Singleton+static getInstance();+operations()-data

soleInstance

<<static>>

Singleton - participantsSingleton - participants

SingletonSingleton– Declare all constructors private and provide Declare all constructors private and provide

only one entry for obtaining a reference to only one entry for obtaining a reference to the sole instancethe sole instance..

ClientClient– Clients can get to the sole instance of Clients can get to the sole instance of

Singleton by asking Singleton to return a Singleton by asking Singleton to return a reference to itreference to it..

CollaborationsCollaborations– A client can only call getInstance() to get a A client can only call getInstance() to get a

reference to the sole instancereference to the sole instance..– A client cannot create any instance of A client cannot create any instance of

SingletonSingleton

Singleton – sample codeSingleton – sample code

class Singleton {class Singleton { // since private no client can // since private no client can

accessaccess // this reference directly// this reference directly private static Singleton private static Singleton

soleInstance soleInstance = new Singleton();= new Singleton(); private int data;private int data; // since protected, no client can // since protected, no client can // create any instance directly// create any instance directly protected Singleton();protected Singleton(); // the only entry for clients to get // the only entry for clients to get

aa // reference to the sole instane// reference to the sole instane public static Singleton public static Singleton

getInstance() {getInstance() { return soleInstance;return soleInstance; }} // other operations// other operations public void operations() { }public void operations() { }}}

class Client1 {class Client1 { void anOperation() {void anOperation() { // Singleton ref = new Singleton();// Singleton ref = new Singleton(); // illegal since Singleton() is // illegal since Singleton() is

protectedprotected Singleton ref = Singleton ref =

Singleton.getInstance();Singleton.getInstance(); ref.operations();ref.operations(); }}} }

class Client2 {class Client2 { void anOperation() {void anOperation() { Singleton ref = Singleton ref =

Singleton.getInstance();Singleton.getInstance(); // use ref// use ref }}}}

NOTE: objects of Client1 and NOTE: objects of Client1 and Client2 would all share the Client2 would all share the same sole instance of same sole instance of Singleton.Singleton.

Singleton – commentsSingleton – comments

Lazy loadingLazy loading– If the object of Singleton is complex, it may take much If the object of Singleton is complex, it may take much

resource to create. We better create the object only when it resource to create. We better create the object only when it is referenced – lazy loadingis referenced – lazy loading

– Change the body of Change the body of getInstance()getInstance() with the following with the following if (soleInstance == null) {if (soleInstance == null) { soleInstance = new Singleton();soleInstance = new Singleton(); }} return soleInstance;return soleInstance; Not thread safe (Java)Not thread safe (Java)

– Two concurrent threads could cause two instances created Two concurrent threads could cause two instances created if executed concurrentlyif executed concurrently

– Solution: Make getInstance() Solution: Make getInstance() synchronizedsynchronized All static members?All static members?

– Since there is only one instance, why don’t we just make all Since there is only one instance, why don’t we just make all members static?members static?

– If yes, then the instance may not fit with the rest of the If yes, then the instance may not fit with the rest of the application: e.g., display(Employee) would not work if application: e.g., display(Employee) would not work if singleton CEO is all staticsingleton CEO is all static

BuilderBuilder

Design purposeDesign purpose– Separate the construction of a Separate the construction of a

complex object from its complex object from its representation so that the same representation so that the same construction process can create construction process can create different representationsdifferent representations

Pattern summaryPattern summary– Use a builder to encapsulate the Use a builder to encapsulate the

representation.representation.

Builder – an exampleBuilder – an example

Language translatorLanguage translator– Translate a Java programs to other Translate a Java programs to other

programming languages (C++, Delphi)programming languages (C++, Delphi)– The translation process is the same for The translation process is the same for

all target languages – mapping all target languages – mapping “import” to something (“include” in “import” to something (“include” in C++)C++)

– Each target language has a Each target language has a builderbuilder to to handle each keyword/structurehandle each keyword/structure

Builder - structureBuilder - structure

Director+buildProduct()

Builder+buildPartA()+buildPartB()+buildPartC()

ProductA

BuilderA+buildPartA()+buildPartB()+buildPartC()+getProductA()

For (every part needed in product) if (part A) builder.buildPartA(); else if (part B) builder.buildPartB(); else if (part C) builder.buildPartC();}

builder

ProductB

Client+madeProduct()

director

BuilderB+buildPartA()+buildPartB()+buildPartC()+getProductB()

Builder - participantsBuilder - participants

ProductA and ProductBProductA and ProductB– Concrete products that are created by different builders.Concrete products that are created by different builders.

Director Director – A class that knows what steps it takes to build a product, but it A class that knows what steps it takes to build a product, but it

does not know how each step is to be carried out or does not does not know how each step is to be carried out or does not know how each part may be added to the final productknow how each part may be added to the final product

BuilderBuilder– Defines an interface for concrete buildersDefines an interface for concrete builders

BuildlerA and BuilderBBuildlerA and BuilderB– Concrete builders who know to construct each part of the Concrete builders who know to construct each part of the

product and add it to the final productproduct and add it to the final product ClientClient

– A client selects a director and a concrete builder to build the A client selects a director and a concrete builder to build the product it needs. The client asks the concrete builder to return product it needs. The client asks the concrete builder to return the final constructed productthe final constructed product

CollaborationsCollaborations– The director knows what parts are needed for the final product The director knows what parts are needed for the final product

and the selected concrete builder knows how to product the part and the selected concrete builder knows how to product the part and add it to the final product. and add it to the final product.

Builder – sequence diagramBuilder – sequence diagram

Client ProductDirector ConcreteBuilder

builder = constructor()

constructor(builder)

constructor()

buildPartA()

buildPartB()

buildPartC()

addPartA()

addPartB()

addPartC()

getProduct()

buildProduct()

Builder – sample codeBuilder – sample code

Class Product {Class Product {addPartA() {}addPartA() {}addPartB() {}addPartB() {}

addPartC() {}addPartC() {}……}}Class ConcreteBuilderClass ConcreteBuilder

implements Builder {implements Builder {Private: Product p;Private: Product p;

ConcreteBuilder() {ConcreteBuilder() {p = new Product();p = new Product();

}}buildPartA() {… p.addPartA(); … }buildPartA() {… p.addPartA(); … }buildPartB() {… p.addPartB(); … }buildPartB() {… p.addPartB(); … }buildPartC() {… p.addPartC(); … }buildPartC() {… p.addPartC(); … }Product getResult() { return p; }Product getResult() { return p; }

}}

Class Director {Class Director {private Builder b;private Builder b;

Director(Builder b) {this.b = b;}Director(Builder b) {this.b = b;}void buildProduct() {void buildProduct() {

for each part in Product {for each part in Product {if (partA) if (partA)

b.buildPartA();b.buildPartA(); else if (partB) else if (partB)

b.buildPartB();b.buildPartB(); else if (partC) else if (partC)

b.buildPartC();b.buildPartC(); }} }}}}client() {client() { Builder b = new Builder b = new

ConcreteBuilder();ConcreteBuilder(); Director d = new Director(b);Director d = new Director(b); d.buildProduct()d.buildProduct() FinalProduct fp = b.getResult();FinalProduct fp = b.getResult();}}

Creational design patternsCreational design patterns

FactoryFactory Abstract FactoryAbstract Factory PrototypePrototype SingletonSingleton BuilderBuilder