designpatterns-08.pdf
TRANSCRIPT
-
7/29/2019 designPatterns-08.pdf
1/32
The Abstract Factory Pattern
and
Singleton Pattern
CSCI 3132 Summer 20111
-
7/29/2019 designPatterns-08.pdf
2/32
SimpleFactoryPa0ern
Client
orderProduct()SimpleFactory
createProduct()
Product
productMethod()
ConcreteProductB
ConcreteProductA
ConcreteProductC
2
-
7/29/2019 designPatterns-08.pdf
3/32
FactoryMethodStructure
3
-
7/29/2019 designPatterns-08.pdf
4/32
CreatorClass
4
-
7/29/2019 designPatterns-08.pdf
5/32
ProductClass
5
-
7/29/2019 designPatterns-08.pdf
6/32
Advantage
TheCreator(PizzaStore)isnot?ghtlycoupledtoanyconcreteproduct(Pizza).
Instan?a?ngconcreteclassesisanareaoffrequentchange.Byencapsula?ngitusingfactoriesweavoidcodeduplica?on
(whichisacodesmell)andmakeiteasiertoembracechange
duringdevelopmentortoperformmaintenance.
TheFactoryPa0ernalsoillustratetheprincipleofcodingtoabstrac?ons(thePizzaproductandthePizzaStoreclientare
abstracts)
6
-
7/29/2019 designPatterns-08.pdf
7/32
Thisispossiblyadevelopmentandmaintenancenighmare7
-
7/29/2019 designPatterns-08.pdf
8/32
ThisiswhattheFactoryMethodpa0ernhasachieved:
8
-
7/29/2019 designPatterns-08.pdf
9/32
TheAbstractFactory
Ourcodecannowworkwithdifferentconcretefactories,throughaFactory
interface(Pizzastore) Whatifweneedtocreateseveraltypesof
products,notjustasingletype
Pizzadough(ThininNY,ThickinChicago)Sauce()
9
-
7/29/2019 designPatterns-08.pdf
10/32
TheAbstractFactory
Answerseemssimple:justuseFactoryMethodpa0erntwice
pizzadough
ThickCrustDough ThinCrustDough
pizzaSauce
PlumTomatoSauce MarinaraSauce
10
-
7/29/2019 designPatterns-08.pdf
11/32
TheAbstractFactory
Thislooksfine butdoesitreflectourinten?on Woulditmakesensetohaveapizza,with
ChicagoThickCrust+NYMarinaraSauce Modeldoesnotincludeanybinding
betweenrelatedproducts
11
-
7/29/2019 designPatterns-08.pdf
12/32
TheAbstractFactory
ADoughandaSaucearenotasseenfromatypepoint-of-viewrelated
Wouldbesomewhatar?ficialorperhapsevenimpossibletointroduceacommonbaseclass
However,wecanenforcethebindingthroughasharedfactoryclass!
12
-
7/29/2019 designPatterns-08.pdf
13/32
TheAbstractFactory
PizzaIngredientFactorycreateDough()
createSauce()
NYPizzaIngredientFactory ChicagoPizzaIngredientFactory
13
-
7/29/2019 designPatterns-08.pdf
14/32
MoreIngredience Wewanttolisttheexactlistofingredientsforeachconcrete
pizza.Forexample:
ChicagoCheesePizza:PlumtomatoSauce,Mozzarella,Parmesan,Oregano;
NewYorkCheesePizza:MarinaraSauce,Reggiano,Garlic. Eachstyleusesadifferentsetofingredients, WecouldchangeimplementPizzaasin:
public class Pizza {
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
. . .
}
14
-
7/29/2019 designPatterns-08.pdf
15/32
andtheconstructornaturallybecomessomethinglike:public Pizza(Dough d, Sauce s, Cheese c, Veggies v,
Pepperoni p, Clams c)
{
dough = d;
sauce = s;
veggies = v;
cheese = c;
pepperoni = p;
clam = c;
}
15
-
7/29/2019 designPatterns-08.pdf
16/32
butthen:public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza(new ThinCrustDough(),
new Marinara(), new Reggiano(), null, null );
} else if (item.equals("veggie")) {
return new NYStyleVeggiaPizza(new ThinCrustDough(),new Marinara(), new Reggiano(), mew Garlic() ,
null);
}
}
This will cause a lot of maintenanceheadaches! Imagine what happens when wecreate a new pizza!
16
-
7/29/2019 designPatterns-08.pdf
17/32
WeknowthatwehaveacertainsetofingredientsthatareusedforNewYork..yetwehavetokeeprepea?ngthatsetwitheach
constructor.Canwedefinethisuniquesetjustonce A`erallwearecrea?ngconcreteinstancesofdough,
ingredientsetc.:
letsusethefactoryofingredients!public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();public Clams createClam();
}
17
-
7/29/2019 designPatterns-08.pdf
18/32
Wethenprogramtotheinterfacebyimplemen?ngdifferentconcreteingredientsfactories.Forexample
herearetheingredientsusedinNewYorkpizzastyle:
public class NYPizzaIngredientFactory : PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
//...
}
18
-
7/29/2019 designPatterns-08.pdf
19/32
OurPizzaclasswillremainanabstractclass:public abstract class Pizza {
protected string name;protected Dough dough;
protected Sauce sauce;
protected ArrayList toppings = new ArrayList();
abstract void Prepare(); //now abstract
public virtual string Bake() {Console.WriteLine("Bake for 25 minutes at 350 \n);
}
public virtual string Cut() {
Console.WriteLine("Cutting the pizza into diagonal slices \n);
}
// ...}
19
-
7/29/2019 designPatterns-08.pdf
20/32
andourconcretePizzasimplybevome:public class CheesePizza : Pizza {PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
thecrea?onoftheingredientsisdelegatedtoafactory.
20
-
7/29/2019 designPatterns-08.pdf
21/32
finallywemusthaveourconcretePizzastoree.g.public class NYPizzaStore : PizzaStore {protected Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
if (item.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
} else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
} else if (item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
}
return pizza;
}
}
21
-
7/29/2019 designPatterns-08.pdf
22/32
AbstractFactoryPa0ern
AbstractFactorycreateProductA()
createProductB()
AbstractProductA
AbstractProductB
Client
ConcreteFactory1
createProductA()createProductB()
ConcreteFactory2
createProductA()createProductB()
ConcreteProductA1
ConcreteProductA2
ConcreteProductB1
ConcreteProductB2
22
-
7/29/2019 designPatterns-08.pdf
23/32
AbstractFactorySummary TheAbstractFactoryPa0ernprovidesaninterfaceforcrea?ngfamiliesofrelatedordependentobjectswithoutspecifying
theirconcreteclasses.
FactoryMethod: UsesinheritancetocreateaConcreteProduct SubclassesdecidewhichConcreteProducttouse
AbstractFactory: Usescomposi?ontocreateobjects Theobjectscreatedwereapartofafamilyofobjects.For
example,NYregionhadaspecificsetofingredients.
AnabstractfactoryactuallycontainsoneormoreFactoryMethods!
23
-
7/29/2019 designPatterns-08.pdf
24/32
TheAbstractFactory
Bymakingacreatorclasswithseveralcreatemethods,werestricttheproductcombina?onsthe
clientcancreate
ThemethodsintheAbstractFactoryareproduct-typedependent,soifweaddanotherproduct,we
needtochangetheinterfaceofthebaseclass
Thisisapricewemustpayforbinding(formally)non-relatedtypestogether
24
-
7/29/2019 designPatterns-08.pdf
25/32
Crea?ngaSingleInstanceofaClass
Insomecasesitmaybenecessarytocreatejustoneinstanceofaclass.
Thismaybenecessarybecause:MorethanoneinstancewillresultinincorrectprogrambehaviorMorethanoneinstancewillresultintheoveruseof
resources
Morethanoneinstancewillresultininconsistentresults
Thereisaneedforaglobalpointofaccess Howwouldyouensurethatjustoneinstance
ofaclassiscreated25
-
7/29/2019 designPatterns-08.pdf
26/32
SingletonPa0ernOverview
Insomecasesthereshouldbeatmostoneinstanceofaclass.
Thisoneinstancemustbeaccessiblebyallclients,e.g.aprinterspooler.
Thisusuallyoccurswhenaglobalresourcehastobeshared.
Thesingletonpa0ernensuresthataclasshasonlyoneinstanceandprovidesonlyonepointofentry.
26
-
7/29/2019 designPatterns-08.pdf
27/32
Implemen?ngtheSingletonPa0ern
Implementaprivateconstructortopreventotherclassesfromdeclaringmorethanone
instance. Implementamethodtocreateasingle
instance.Makethismethodsta?c.
Createalazyinstanceoftheclassintheclass. Makethedataelementsta?c.
27
-
7/29/2019 designPatterns-08.pdf
28/32
ThreadExample
A A dual processor machine, with two threads calling thegetInstance() method for the chocolate boiler
Thread1 Thread2
public stat ChocolateBoiler!! getInstance()!public stat ChocolateBoiler!! getInstance()!
if (uniqueInstance == null)!if (uniqueInstance == null)!
uniqueInstance = !new ChocolateBoiler()!
uniqueInstance = !new ChocolateBoiler()!
return uniqueInstance;!return uniqueInstance;! 28
-
7/29/2019 designPatterns-08.pdf
29/32
ProblemswithMul?threading
Inthecaseofmul?threadingwithmorethanoneprocessorthegetInstance()methodcouldbecalledatmoreorlessthesame?meresul?ngintomorethanoneinstancebeingcreated.
Possiblesolu?ons: SynchronizethegetInstance()method DonothingifthegetInstance()methodisnotcri?caltothe
applica?on.
Movetoaneagerlycreatedinstanceratherthanalazilycreatedone.
29
-
7/29/2019 designPatterns-08.pdf
30/32
SynchronizingthegetInstance()
Method Codepublic static synchronized Singleton getInstance(){
}
Disadvantagesynchronizingcandecreasesystemperformancebyafactorof1.
30
-
7/29/2019 designPatterns-08.pdf
31/32
UseanEagerlyCreatedInstance
RatherthanaLazyOne Code://Data elements
public static Singleton uniqueInstance = newSingleton()
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance
}
DisadvantageMemorymaybeallocated andnotused.
31
-
7/29/2019 designPatterns-08.pdf
32/32
SingletonPa0ernSummary
Thesingletonpa0ernensuresthatthereisjustoneinstanceofaclass.
Thesingletonpa0ernprovidesaglobalaccesspoint.
Thepa0ernisimplementedbyusingaprivateconstructorandasta?cmethodcombinedwithasta?cvariable.
Possibleproblemswithmul?threading. VersionsofJavaearlierthat1.2automa?cally
clearsingletonsthatarenotbeingaccessedaspartofgarbagecollec?on.
32