Presentation is loading. Please wait.

Presentation is loading. Please wait.

Factory Patterns. RHS – SOC 2 Being less concrete One important OO principle is: ”Program to an interface, not an implementation” Interfaces reduces the.

Similar presentations


Presentation on theme: "Factory Patterns. RHS – SOC 2 Being less concrete One important OO principle is: ”Program to an interface, not an implementation” Interfaces reduces the."— Presentation transcript:

1 Factory Patterns

2 RHS – SOC 2 Being less concrete One important OO principle is: ”Program to an interface, not an implementation” Interfaces reduces the coupling between code and concrete types Code does not need to know the concrete type of an object

3 RHS – SOC 3 Being less concrete Animal sleep() makeSound() lookForFood() Dog sleep() makeSound() lookForFood() Horse sleep() makeSound() lookForFood()

4 RHS – SOC 4 Being less concrete Animal oneAnimal = new Horse(); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): …

5 RHS – SOC 5 Being less concrete Animal oneAnimal = new Dog(); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): …

6 RHS – SOC 6 Being less concrete This is fine, but we still need to be concrete when creating an object Also, we might need to choose – at run-time – between various concrete types

7 RHS – SOC 7 Being less concrete Animal oneAnimal; … if (needToRide) oneAnimal = new Horse(); else if (mustBeMammal) oneAnimal = new Dog(); else oneAnimal = new Parrot(); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): …

8 RHS – SOC 8 Being less concrete Is anything wrong with this…? What if we need to add some new concrete types? In that case, we will need to change the code in order to include the new types ”Closed for modification, open for extension…”

9 RHS – SOC 9 Being less concrete We want to isolate the references to concrete types to another class One class produces concrete objects, using their concrete types Another class processes the objects, knowing only the interface The processing class can then be closed for modification

10 RHS – SOC 10 Being less concrete A class which produces objects is usually called a Factory Class A factory class usually has a single method: create(…) The create method often – but not always – takes a parameter, defining what concrete object to create

11 RHS – SOC 11 Being less concrete Animal sleep() makeSound() lookForFood() Dog sleep() makeSound() lookForFood() Horse sleep() makeSound() lookForFood() AnimalFactory Animal create(String info)

12 RHS – SOC 12 Being less concrete public class AnimalFactory { public Animal create(String info) { if (info.equals(”Dog”)) return new Dog(); else if (info.equals(”Horse”)) return new Horse(); else if (info.equals(”Parrot”)) return new Parrot(); else return null; }

13 RHS – SOC 13 Being less concrete AnimalFactory fac; … Animal oneAnimal = fac.create(”Dog”); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): …

14 RHS – SOC 14 Being less concrete Have I achieved something, or am I just moving code around…? With this setup, we can now parameterise the processing code further This removes the last references to concrete types

15 RHS – SOC 15 Being less concrete public void processAnAnimal(String type) { AnimalFactory fac = new AnimalFactory(); … Animal oneAnimal = fac.create(type); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): … } Type specifi- cation is a parameter

16 RHS – SOC 16 Being less concrete public void processAnAnimal (String type, AnimalFactory fac) { Animal oneAnimal = fac.create(type); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): … } Type specifi- cation and object factory are parameters

17 RHS – SOC 17 Being less concrete This pattern is known as Simple Factory We have separated code for producing objects, and code for processing objects Processing code only knows about the interface Fewer responsibilities per class – ”Classes should only have one reason to change”

18 RHS – SOC 18 Exercises Download the NetBeans project FactoryExample from the Website (go to Classes, Week 43) Examine the code; we have defined a Pizza interface, and three concrete pizza classes SevenSeasPizza, TorinoPizza and Vegetarian pizza We have also defined a base class for a PizzaStore, and two concrete pizza stores, PizzaStoreA and PizzaStoreB Examine the difference between PizzaStoreA and PizzaStoreB. The first one creates pizza objects directly in the code, while the second one uses a simple factory (SimplePizzaFactory) Try to add a new pizza type RomaPizza (remember it must implement the Pizza interface), and update the pizza factory. Do you need to change the code in PizzaStoreA as well? Do you need to change the code in PizzaStoreB as well?

19 RHS – SOC 19 Abstraction to the next level The processing code needs a parameter which carries the type information for the object being created However, we also suggested that the factory itself could be a parameter Why would we do that….?

20 RHS – SOC 20 Abstraction to the next level public void processAnAnimal (String type, AnimalFactory fac) { Animal oneAnimal = fac.create(type); … oneAnimal.sleep(); oneAnimal.makeSound(); oneAnimal.lookForFood(): … } Type specifi- cation and object factory are parameters

21 RHS – SOC 21 Abstraction to the next level Consider a word processor: –A document is composed of various typographic objects, like Heading, Emphasis, and so on –All such classes implement the interface Typo –Given some input source, a piece of code must produce a list of Typo objects

22 RHS – SOC 22 Abstraction to the next level // Part of input processing code TypoFactory theTypoFactory; public void createDocument(DocInput in) { ArrayList doc = new ArrayList (); while (in.hasNext()) { TypoInput tyIn = in.next(); Typo typ = makeTypo(tyIn); doc.add(typ); }

23 RHS – SOC 23 Abstraction to the next level // Part of input processing code private Typo makeTypo(TypoInput in) { String text = in.getText(); String type = in.getType(); Typo theTypo = theTypoFactory.create(type); thetypo.addText(text); return theTypo; }

24 RHS – SOC 24 Abstraction to the next level // TypoFactory code private Typo create(String type) { if (type.equals(”Heading”)) return new Heading(); else if (type.equals(”Emphasis”)) return new Emphasis();... else return null; }

25 RHS – SOC 25 Abstraction to the next level The code processing the input does not know about concrete Typo classes – good But the code is still ”constrained”… What is a Typo object really – it is a ”binding” between a text and a certain way of formatting the text Different concrete Typo classes provide different bindings

26 RHS – SOC 26 Abstraction to the next level A Heading might be –Font size 24 –Bold –Calibri font An Emphasis might be –Bold –Red font color

27 RHS – SOC 27 Abstraction to the next level A Typo factory thus defines a set of bindings between text and formatting – a layout What if we wish to change the layout of a document? We could then just define a different Typo factory, with different bindings

28 RHS – SOC 28 Abstraction to the next level // Part of input processing code TypoFactoryFormalLayout theTypoFactory; public void createDocument(DocInput in) { ArrayList doc = new ArrayList (); while (in.hasNext()) { TypoInput tyIn = in.next(); Typo typ = makeTypo(tyIn); doc.add(typ); } Just change the type of the Typo factory…

29 RHS – SOC 29 Abstraction to the next level This solution is still quite static Changing to a different factory requires code modification Why not use interfaces once again! We could also define an interface for the factory side, making the processing code independent of a specific factory

30 RHS – SOC 30 Abstraction to the next level Typo addText() TypoFactory Typo create(…)

31 RHS – SOC 31 Abstraction to the next level TypoTypoFactory TypoFactory- FormalLayout TypoFactory- SmartLayout

32 RHS – SOC 32 Abstraction to the next level TypoTypoFactory TypoHeading- Formal TypoEmphasis- Formal TypoHeading- Smart TypoEmphasis- Smart

33 RHS – SOC 33 Abstraction to the next level TypoHeading- Formal TypoEmphasis- Formal TypoHeading- Smart TypoEmphasis- Smart TypoFactory- FormalLayout TypoFactory- SmartLayout

34 RHS – SOC 34 Abstraction to the next level The factory for Formal layout only knows the concrete classes TypoHeading- Formal and TypoEmphasisFormal The factory for Smart layout only knows the concrete classes TypoHeadingSmart and TypoEmphasisSmart The factory interface only knows about the Typo interface

35 RHS – SOC 35 Abstraction to the next level // A configurable document creator class public class DocumentCreator { TypoFactory typoFac; public DocumentCreator(TypoFactory typoFac) { this.typoFac = typoFac; } public void createDocument(DocInput in) {...} }

36 RHS – SOC 36 Abstraction to the next level public void createFormalDocument() { TypoFactory typoFac = new TypoFactoryFormalLayout(); DocumentCreator docCre = new DocumentCreator(typoFac); docCre.createDocument(getDocInput()); }

37 RHS – SOC 37 Abstraction to the next level Note that the only thing that changes between two TypoFactory implementa- tions is the create method We may include concrete methods in the Typo interface – making it an abstract class – if it makes sense This is known as the Factory Mehtod pattern

38 RHS – SOC 38 The Factory method pattern Product Factory create() someMethod() ConcreteFactory create() ConcreteProduct

39 RHS – SOC 39 Exercises Download the NetBeans project FactoryMethodExample from the Website (go to Classes, Week 43) Examine the code; we have introduced two styles of pizza; LA-style (Los Angeles), and SF-style (San Francisco), so all pizzas now come in these two variants. Corresponding pizza classes have been created A PizzaFactory interface has also been included, with a single method createPizza. Two concrete pizza factories have been implemented, corresponding to the two pizza styles (PizzaFactoryLAStyle and PizzaFactoryLAStyle) A new pizza store PizzaStoreC has been implemented. This pizza store takes a PizzaFactory object as a parameter to its constructor A test of the new pizza store is found in Main. Try it out! See what happens if you change the parameter to the constructor If time permits, try to implement a third style for pizzas, including new pizza classes and a new pizza factory class

40 RHS – SOC 40 The Abstract Factory Our code can now work with different concrete factories, through a Factory interface What if we need to create several types of ”products”, not just a single type? –Typo – formattings of text –Graphic – formattings of graphic objects

41 RHS – SOC 41 The Abstract Factory Answer seems simple: just use Factory Method pattern twice TypoTypoFactory TypoFactory- FormalLayout TypoFactory- SmartLayout GraphicGraphicFactory GraphicFactory- FormalLayout GraphicFactory- SmartLayout

42 RHS – SOC 42 The Abstract Factory This looks fine… …but does it reflect our intention? Would it make sense to have a document, with –text using Formal layout –graphics using Smart layout Model does not include any ”binding” between related products

43 RHS – SOC 43 The Abstract Factory public void createFormalDocument() { TypoFactory tFac = new TypoFactoryFormalLayout(); GraphicFactory gFac = new GraphicFactorySmartLayout(); DocumentCreator docCre = new DocumentCreator(tFac,gFac); docCre.createDocument(getDocInput()); } Oooppss!

44 RHS – SOC 44 The Abstract Factory A Typo and a Graphic are not – as seen from a type point-of-view – related Would be somewhat artificial – or perhaps even impossible – to introduce a common base class However, we can enforce the binding through a shared factory class!

45 RHS – SOC 45 The Abstract Factory DocItemFactory createTypo() createGraphic() FormalDocItemFactorySmartDocItemFactory

46 RHS – SOC 46 The Abstract Factory public void createFormalDocument() { DocItemFactory fac = new FormalDocItemFactory (); DocumentCreator docCre = new DocumentCreator(fac); docCre.createDocument(getDocInput()); }

47 RHS – SOC 47 The Abstract Factory public void createDocument(DocInput in) {... Typo aTypo = theFactory.createTypo(typoInfo);... Graphic aGraphic = theFactory.createGraphic(graphicInfo);... } Using the same factory for creating Typo and Graphic objects!

48 RHS – SOC 48 The Abstract Factory This pattern is known as the Abstract Factory pattern By making a creator class with several create… methods, we restrict the product combinations the client can create

49 RHS – SOC 49 The Abstract Factory The methods in the Abstract Factory are product-type dependent, so if we add another product, we need to change the interface of the base class This is a price we must pay for binding (formally) non-related types together Patterns are also compromises…

50 RHS – SOC 50 Exercises Download the NetBeans project AbstractFactoryExample from the Website (go to Classes, Week 43) Examine the code; we have now included a Beverage as well. We assume that a pizza is always served with a beverage. In L.A., the beverage is always cola, and in S.F., the beverage is always coffee Classes representing beverages have been included in the code, along with two beverage factories. In the new pizza store PizzaStoreD, the store is now initialised with a pizza factory and a beverage factory. See the test in Main. However, there is a problem, since we can choose to use two factories representing different styles… In order to fix this problem, we introduce a MealFactory interface, with two methods createPizza and createBeverage. We have also included two concrete implementations of the interface, MealFactoryLAStyle and MealFactorySFStyle. Inspect the implementation of the concrete meal factories and PizzaStoreE, to see how the problem of mixing factories of different styles have been eliminated If time permits, experiment with adding a ”side order” to a meal, like french fries, pie, ice cream, or whatever you can imagine


Download ppt "Factory Patterns. RHS – SOC 2 Being less concrete One important OO principle is: ”Program to an interface, not an implementation” Interfaces reduces the."

Similar presentations


Ads by Google