/
Factory Design Patterns CECS277 Factory Design Patterns CECS277

Factory Design Patterns CECS277 - PowerPoint Presentation

piper
piper . @piper
Follow
66 views
Uploaded On 2023-06-24

Factory Design Patterns CECS277 - PPT Presentation

Fall 2017 Mimi Opkins Factory Pattern Word of the Day Factory Different Flavors Simple Factory Factory Method Abstract Factory 2 6262017 What Pattern should we consider We need to manage a shared network printer ID: 1002716

public pizza abstract factory pizza public factory abstract 2017 class pizzastore return type create createpizza string method cheese item

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Factory Design Patterns CECS277" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

1. Factory Design PatternsCECS277 Fall 2017Mimi Opkins

2. Factory PatternWord of the Day = FactoryDifferent FlavorsSimple FactoryFactory MethodAbstract Factory 26/26/2017

3. What Pattern should we consider?We need to manage a shared network printer. We create an algorithm for renting movies online. MoviesOnline.com and ObjectvilleMovies both use the exact same algorithm, but MoviesOnline.com would like the additional capability of displaying the next movie in the queue after a movie is rented. You are creating a character for a computer game. You want the character to be able to support different victory dances. The computer should be able to assign different victory dances during game play.36/26/2017

4. Pizza Store in ObjectvilleWe need a pizza store that can create pizza.The customer will order a specific type of pizza:CheeseVeggieGreekPepperonietc Each order request is for one type of pizza only.46/26/2017

5. PizzaStore in ObjectvilleDuring the ordering of a Pizza, we need to perform certain actions on it:PrepareBakeCutBoxWe know that all Pizzas must perform these behaviors. In addition, we know that these behaviors will not change during runtime. (i.e. the Baking time for a Cheese Pizza will never change!)Question: Should these behaviors (prepare, bake, etc) be represented using Inheritance or Composition?56/26/2017

6. PizzaStore in Objectville (pg 112 top) public Pizza orderPizza(String type) { Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }Creating an instance of Pizza() doesn’t make sense here because we know there are different types of Pizza.66/26/2017This method is responsible for creating the pizza. It calls methods to prepare, bake, etc. Pizza is returned to caller.

7. PizzaStore in Objectville public Pizza orderPizza(String type) { if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }76/26/2017Code that variesA parameter indicating typeCode that stays the same

8. PizzaStore in Objectville (cont)Pressure is on for change…Now we get some new types of Pizza (Clam, Veggie)Every time there is a change, we would need to break into this code and update the If/Else statement. (and possibly introduce bugs in our existing code).86/26/2017

9. Solution? Move the creation of Pizzas into a separate object! public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }}96/26/2017

10. SimplePizzaFactoryAdvantage: We have one place to go to add a new pizza.Disadvantage: Whenever there is a change, we need to break into this code and add a new line. (but at least it is in one place!!)106/26/2017

11. Rework of PizzaStore public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type) { Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }}116/26/2017Store is composed of a factory.Creation of pizza is delegated to factory.

12. Simple Factory Defined This is not an official pattern, but it is commonly used.Not a bad place to start.When people think of “Factory”, they may actually be thinking of this.126/26/2017

13. Change Now Occurs…The PizzaStore is very popular and it needs to be franchised.New York is interestedChicago is interestedAnd perhaps one day Fairfax…Since PizzaStore is already composed of a Simple Factory, then this should be easy! Let’s just create PizzaStore with a different SimpleFactory.136/26/2017

14. Example //NY Pizza Factory has a different if/else logicNYPizzaFactory nyFactory = new NYPizzaFactory(); //Create the Pizza Store, but use this Simple Factory //insteadPizzaStore nyStore = new PizzaStore(nyFactory);//Order pizzanyStore.order(“Veggie”);146/26/2017

15. More change happens…New York likes the PizzaStore, but they want to add more functionality, such as schedule a delivery. New York attempts to extend PizzaStore…public class NYPizzaStore extends PizzaStore { public void ScheduleDelivery() { … }}156/26/2017

16. More change happens… (cont)NYPizzaFactory nyFactory = new NYPizzaFactory(); NYPizzaStore nyStore = new NYPizzaStore(nyFactory);//Order pizzanyStore.order(“Veggie”);myStore.ScheduleDelivery();New York says the following:We only have one way to create pizzas; therefore, we don’t need to use composition for the pizza creation. We are not happy that we have to create our extended Pizza store and create a unique factory for creating pizzas. These two classes have a one-to-one relationship with each other. Can’t they be combined??166/26/2017

17. What New York wantsA framework so that NY can do the following:Create pizzas in a NY styleAdd additional functionality that is applicable to NY only.176/26/2017

18. A Framework for Pizza Store public abstract class PizzaStore { abstract Pizza createPizza(String item); public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); pizza.prepare(); . . . return pizza; }}186/26/2017NOTE: We are using inheritance here to create the pizzas, not composition. Also, the constructor for PizzaStore has been removed.

19. NYPizzaStorepublic class NYPizzaStore extends PizzaStore { Pizza createPizza(String item) { if (item.equals("cheese")) { return new NYStyleCheesePizza(); } else if (item.equals("veggie")) { return new NYStyleVeggiePizza(); } else if (item.equals("clam")) { return new NYStyleClamPizza(); } else if (item.equals("pepperoni")) { return new NYStylePepperoniPizza(); } else return null; } void ScheduleDelivery();}196/26/2017The subclass is defining how the pizza is created….and it is also providing unique functionality that is applicable to New York.

20. Factory Methodpublic abstract class PizzaStore { abstract Pizza createPizza(String item); public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); pizza.prepare(); . . . return pizza; }}206/26/2017Factory Method simply sets up an interface for creating a Product (in this case, a type of Pizza). Subclasses decide which specific Product to create.

21. Test Drive 1) PizzaStore nyStore = new NYPizzaStore();2) nyStore.orderPizza("cheese");3)Calls createPizza(“cheese”). The NYPizzaStore version of createPizza is called. It returns a NYStyleCheesePizza();4) orderPizza continues to call the “parts that do not vary”, such as prepare, bake, cut, box. 216/26/2017

22. Factory Method DefinedGoF Intent: “Defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”226/26/2017

23. Definitions Product - abstraction of the object that we need to create (Pizza)Concrete Product – implementations of a specific Product (NYStyleCheesePizza)Creator – abstraction of the object that will create a Product (PizzaStore). Contains factory method.Concrete Creator – implementation of a Creator that creates a specific ConcreteProduct (NYPizzaStore)236/26/2017

24. IMPORTANTThe Factory Method should just return a ConcreteProduct.246/26/2017

25. Labpublic abstract class PizzaStore { abstract Pizza createPizza(String item); public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); . . . return pizza; }}256/26/2017 Did we separate out the parts that vary from the parts that do not vary? Did we Program to an Interface, not an Implementation? Does the Hollywood Principle apply here? Did we favor composition over inheritance?

26. Parameterized Factory MethodAnother example is actually a Parameterized Factory Method since it can make more than one object (based on some input parameter). abstract Pizza createPizza(String item);266/26/2017

27. Simple Factory Methodpublic abstract class PizzaStore { abstract Pizza createPizza(); //no parameter! public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); . . . }}public class NYPizzaStore extends PizzaStore { Pizza createPizza() { return new NYStylePizza(); //just one product returned }}276/26/2017

28. Simple Factory Method (with Default)public abstract class PizzaStore { void Pizza createPizza() { return new DefaultPizza(); } public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); . . . }}286/26/2017In this example, there is default Product created (DefaultPizza).

29. SimUDuck public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); }}296/26/2017Developer would have to know to do this. The design does not enforce it.MallardDuck is tied to two specific implementations.

30. Beforepublic abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } //Not shown: setFlyBehavior, setQuackBehavior //Not shown: abstract display method, fly, quack} 306/26/2017

31. Afterpublic abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; abstract FlyBehavior createFly(); abstract QuackBehavior createQuack(); public Duck() { flyBehavior = createFly(); quackBehavior = createQuack(); }} 316/26/2017Factory Methods

32. Now we create MallardDuck…public class MallardDuck extends Duck { public MallardDuck() { } FlyBehavior createFly() { return FlyWithWings(); } QuackBehavior createQuack() { return Quack(); } }326/26/2017Developer is “forced” to specify implementations of Fly and Quack.Note that the constructor is empty.

33. Alternative Design: Default Behaviorpublic abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; FlyBehavior createFly() { return DefaultFly(); } QuackBehavior createQuack() { return DefaultQuack(); } public Duck() { flyBehavior = createFly(); quackBehavior = createQuack(); }} 336/26/2017MallardDuck does not have to implement these methods.

34. Factory Method and Templatepublic abstract class CaffeineBeverage { final void prepareRecipe() { boilWater(); brew(); pourInCup(); Condiment c = createCondiment(); addCondiments(c); } abstract void brew(); abstract Condiment createCondiment(); void addCondiments(Condiment c) { //add condiment c }}346/26/2017Example re-worked here

35. SummaryPattern Name – Factory MethodProblem – Do not want our framework to be tied to a specific implementation of an object.Solution Let subclass decide which implementation to use (via use of an abstract method)Tie the Creator with a specific Product ImplementationConsequencesSimple Factory MethodSimple Factory Method with Default BehaviorParameterized Factory MethodFactory and Template Together356/26/2017

36. Changes..Objectville Pizza HQ gets complaints that the different franchises are not using quality ingredients. They decide that all Pizzas must be composed of the following ingredients:Dough, Sauce, Cheese, Veggies, Pepperoni, and Clams.New York says those ingredients are fine, but they want to use their own regional ingredients for all types of pizza, for exampleDough = Thin Crust DoughSauce = Marinara Cheese = ReggianoVeggies = Garlic, Onion366/26/2017

37. Pizza public class Pizza { Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; . . .}376/26/2017Pizza becomes composed of different ingredients.Question: How do we get these ingredients associated with a Pizza??

38. One idea…Constructor w/many parameterspublic class Pizza { public Pizza(Dough d, Sauce s, Cheese c, Veggies v, Pepperoni p, Clams c) { this.dough = d; this.sauce = s; this.veggies = v; this.cheese = c; this.pepperoni = p; this.clam = c; }}386/26/2017Makes sense…whenever you create a pizza, you must specify these ingredients…

39. Rework NYPizzaStorepublic 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) }}396/26/2017This will cause a lot of maintenance headaches!!! Imagine what happens when we create a new pizza! We know that we have a certain set of ingredients that are used for New York..yet we have to keep repeating that set with each constructor. Can we define this unique set just once??

40. PizzaIngredientFactorypublic interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); }406/26/2017Create an interface for creating the different ingredients of Pizza.Note that each ingredient of Pizza has a corresponding method defined in the interface.

41. NYPizzaIngredientFactory public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() { return new ThinCrustDough(); } public Sauce createSauce() { return new MarinaraSauce(); } public Cheese createCheese() { return new ReggianoCheese(); } . . . }416/26/2017Here we see the set of ingredients that are specific to the NY region.Note that each time a createXXX() method is called, a new instance is returned. This will be important later on.

42. CheesePizza public class CheesePizza extends Pizza { PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } void prepare() { dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); }}426/26/2017Instead of many ingredient parameters, we just pass one.Does this remind you of another pattern??Creation delegatedNote: Not all ingredients have to be used!

43. NYPizzaStore (pg 152)public class NYPizzaStore extends 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;436/26/2017The specific ingredient factory is defined once for the NY region.

44. Abstract Factory DefinedGoF Intent: “Provides an interface for creating families of related or dependent objects without specifying their concrete classes.”446/26/2017

45. Factory Method vs. Abstract FactoryFactory MethodUses inheritance to create a Concrete ProductSub classes decide which Concrete Product to useAbstract FactoryUses composition to create objectsThe objects created were a part of a family of objects. For example, NY region had a specific set of ingredients.An abstract factory actually contains one or more Factory Methods!456/26/2017

46. Database ExampleImagine you wanted to created a database manager object as an enterprise component. This object must not be tied to a specific database implementation.Each specific database uses different objects:ConnectionCommandAdapterData ReaderOracle, SQL Server, Informix, etc will have their own version of these Sub Products.466/26/2017

47. DatabaseFactorypublic abstract class DatabaseFactory{public abstract IDbCommand CreateCommand();public abstract IDbCommand CreateCommand(string cmdText);public abstract IDbCommand CreateCommand(string cmdText, IDbConnection cn);public abstract IDbConnection CreateConnection();public abstract IDbConnection CreateConnection(string cnString);public abstract IDbDataAdapter CreateDataAdapter();public abstract IDbDataAdapter CreateDataAdapter(IDbCommand selectCmd);public abstract IDataReader CreateDataReader(IDbCommand dbCmd);}476/26/2017Each database implementation (Oracle, SQL Server, etc) will need to create their own version of this DatabaseFactory.The specific DatabaseFactory must be sent to the constructor of the framework class DatabaseManager.

48. Abstract Factory and SingletonIf you have many different Abstract Factories, you probably just need one instance of each abstract factory.You can use a Singleton to define each Abstract Factory.486/26/2017

49. A more interesting case…What if NY Pizza Store wanted the flexibility to change their ingredients all the time?? For example, one day use:ThickCrust Dough (not Thin)Marina Sauce (which was previously used)Provolone Cheese (not Reggiano)And then next week the cheese needs to be changed to Cheddar (since Provolone shipment didn’t come in time).496/26/2017

50. What will happen??Class Explosion!We would need an Abstract Factory for every possible combination…and when we add a new ingredient, we could have to create even more Abstract Factories.506/26/2017

51. Solution: Abstract Factory and PrototypeWhen we create the abstract factory, pass the different applicable products in the constructor.PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory (new ThinCrustDough(), new MarinaraSauce(), new Provolone() );These products could easily come from an XML file or even by the user during runtime.516/26/2017

52. Solution: Abstract Factory and PrototypeThe abstract factory can then be passed to the different types of Pizzas.When a method is called (ie, createDough, createSauce), a cloned copy of the Product is returned.This ensures that each call to a createXXX method returns a unique instance. Note: In our standard abstract factory, a unique instance is returned every time you call a createXXX method.526/26/2017

53. Abstract Factory: Last Thoughts This may be a hard pattern to “see” during the initial design process.You may encounter this pattern during refactoring.536/26/2017

54. SummaryPattern Name – Abstract FactoryProblem – Need to way to create a family of products SolutionCreate an interface for creating productsConsequencesObjects are created using interfaceComposition is used to create objectsAbstract Factory and SingletonAbstract Factory and Prototype546/26/2017

55. CreditsJonathan Simonjonathan_simon@yahoo.com