1 / 47

Factory Patterns

Factory Patterns. 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. Being less concrete. Animal sleep() makeSound()

aderyn
Download Presentation

Factory Patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Factory Patterns

  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 RHS – SWC

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

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

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

  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 RHS – SWC

  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(): … RHS – SWC

  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…” RHS – SWC

  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 RHS – SWC

  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 RHS – SWC

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

  12. Being less concrete publicclass AnimalFactory { public Animal create(String info) { if (info.equals(”Dog”)) return new Dog(); elseif (info.equals(”Horse”)) return new Horse(); elseif (info.equals(”Parrot”)) returnnew Parrot(); else returnnull; } } RHS – SWC

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

  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 RHS – SWC

  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 RHS – SWC

  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 RHS – SWC

  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” RHS – SWC

  18. 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….? RHS – SWC

  19. 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 RHS – SWC

  20. Abstraction to the next level • Consider a word processor: • A document is composed of various typo-graphic 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 RHS – SWC

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

  22. 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; } RHS – SWC

  23. Abstraction to the next level // TypoFactory code private Typo create(String type) { if (type.equals(”Heading”)) returnnew Heading(); elseif (type.equals(”Emphasis”)) returnnew Emphasis(); ... else returnnull; } RHS – SWC

  24. 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 RHS – SWC

  25. Abstraction to the next level • A Heading might be • Font size 24 • Bold • Calibri font • An Emphasis might be • Bold • Red font color RHS – SWC

  26. 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 RHS – SWC

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

  28. 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 RHS – SWC

  29. Abstraction to the next level TypoFactory Typo create(…) Typo addText() RHS – SWC

  30. Abstraction to the next level TypoFactory Typo TypoFactory- FormalLayout TypoFactory- SmartLayout RHS – SWC

  31. Abstraction to the next level TypoFactory Typo TypoHeading- Formal TypoHeading- Smart TypoEmphasis- Formal TypoEmphasis- Smart RHS – SWC

  32. Abstraction to the next level TypoHeading- Formal TypoHeading- Smart TypoFactory- FormalLayout TypoFactory- SmartLayout TypoEmphasis- Formal TypoEmphasis- Smart RHS – SWC

  33. 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 RHS – SWC

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

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

  36. 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 RHS – SWC

  37. The Factory method pattern Factory create() someMethod() Product ConcreteFactory create() ConcreteProduct RHS – SWC

  38. 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 RHS – SWC

  39. The Abstract Factory • Answer seems simple: just use Factory Method pattern twice TypoFactory Typo GraphicFactory Graphic TypoFactory- FormalLayout TypoFactory- SmartLayout GraphicFactory- FormalLayout GraphicFactory- SmartLayout RHS – SWC

  40. 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 RHS – SWC

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

  42. 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! RHS – SWC

  43. The Abstract Factory DocItemFactory createTypo() createGraphic() FormalDocItemFactory SmartDocItemFactory RHS – SWC

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

  45. 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! RHS – SWC

  46. 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 RHS – SWC

  47. 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… RHS – SWC

More Related