Factory Patterns

  • View
    20

  • Download
    0

Embed Size (px)

DESCRIPTION

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() - PowerPoint PPT Presentation

Transcript

  • Factory Patterns

  • Being less concreteOne important OO principle is: Program to an interface, not an implementationInterfaces reduces the coupling between code and concrete typesCode does not need to know the concrete type of an object

  • Being less concreteAnimalsleep()makeSound()lookForFood()Dogsleep()makeSound()lookForFood()Horsesleep()makeSound()lookForFood()

  • Being less concreteAnimal oneAnimal = new Horse();oneAnimal.sleep();oneAnimal.makeSound();oneAnimal.lookForFood():

  • Being less concreteAnimal oneAnimal = new Dog();oneAnimal.sleep();oneAnimal.makeSound();oneAnimal.lookForFood():

  • Being less concreteThis is fine, but we still need to be concrete when creating an objectAlso, we might need to choose at run-time between various concrete types

  • Being less concreteAnimal oneAnimal;if (needToRide)oneAnimal = new Horse();else if (mustBeMammal)oneAnimal = new Dog();elseoneAnimal = new Parrot();oneAnimal.sleep();oneAnimal.makeSound();oneAnimal.lookForFood():

  • Being less concreteIs 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 typesClosed for modification, open for extension

  • Being less concreteWe want to isolate the references to concrete types to another classOne class produces concrete objects, using their concrete typesAnother class processes the objects, knowing only the interfaceThe processing class can then be closed for modification

  • Being less concreteA class which produces objects is usually called a Factory ClassA factory class usually has a single method: create()The create method often but not always takes a parameter, defining what concrete object to create

  • Being less concreteAnimalsleep()makeSound()lookForFood()Dogsleep()makeSound()lookForFood()Horsesleep()makeSound()lookForFood()AnimalFactoryAnimal create(String info)

  • Being less concretepublic 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;}}

  • Being less concreteAnimalFactory fac;Animal oneAnimal = fac.create(Dog);oneAnimal.sleep();oneAnimal.makeSound();oneAnimal.lookForFood():

  • Being less concreteHave I achieved something, or am I just moving code around?With this setup, we can now parameterise the processing code furtherThis removes the last references to concrete types

  • Being less concretepublic 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

  • Being less concretepublic 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

  • Being less concreteThis pattern is known as Simple FactoryWe have separated code for producing objects, and code for processing objectsProcessing code only knows about the interfaceFewer responsibilities per class Classes should only have one reason to change

  • ExercisesDownload 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 pizzaWe have also defined a base class for a PizzaStore, and two concrete pizza stores, PizzaStoreA and PizzaStoreBExamine 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?

  • Abstraction to the next levelThe processing code needs a parameter which carries the type information for the object being createdHowever, we also suggested that the factory itself could be a parameterWhy would we do that.?

  • Abstraction to the next levelpublic 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

  • Abstraction to the next levelConsider a word processor:A document is composed of various typographic objects, like Heading, Emphasis, and so onAll such classes implement the interface TypoGiven some input source, a piece of code must produce a list of Typo objects

  • Abstraction to the next level// Part of input processing codeTypoFactory theTypoFactory;

    public void createDocument(DocInput in){ArrayList doc = new ArrayList();while (in.hasNext()){ TypoInput tyIn = in.next(); Typo typ = makeTypo(tyIn); doc.add(typ);}}

  • Abstraction to the next level// Part of input processing codeprivate Typo makeTypo(TypoInput in){String text = in.getText();String type = in.getType();

    Typo theTypo = theTypoFactory.create(type);thetypo.addText(text);

    return theTypo;}

  • Abstraction to the next level// TypoFactory codeprivate Typo create(String type){if (type.equals(Heading))return new Heading();else if (type.equals(Emphasis))return new Emphasis();...elsereturn null;}

  • Abstraction to the next levelThe code processing the input does not know about concrete Typo classes goodBut the code is still constrainedWhat is a Typo object really it is a binding between a text and a certain way of formatting the textDifferent concrete Typo classes provide different bindings

  • Abstraction to the next levelA Heading might beFont size 24BoldCalibri fontAn Emphasis might beBoldRed font color

  • Abstraction to the next levelA Typo factory thus defines a set of bindings between text and formatting a layoutWhat if we wish to change the layout of a document?We could then just define a different Typo factory, with different bindings

  • Abstraction to the next level// Part of input processing codeTypoFactoryFormalLayout 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

  • Abstraction to the next levelThis solution is still quite staticChanging to a different factory requires code modificationWhy not use interfaces once again!We could also define an interface for the factory side, making the processing code independent of a specific factory

  • Abstraction to the next levelTypoaddText()

    TypoFactoryTypo create()

  • Abstraction to the next levelTypo

    TypoFactoryTypoFactory-FormalLayoutTypoFactory-SmartLayout

  • Abstraction to the next levelTypo

    TypoFactoryTypoHeading-FormalTypoEmphasis-FormalTypoHeading-SmartTypoEmphasis-Smart

  • Abstraction to the next levelTypoHeading-FormalTypoEmphasis-FormalTypoHeading-SmartTypoEmphasis-SmartTypoFactory-FormalLayoutTypoFactory-SmartLayout

  • Abstraction to the next levelThe factory for Formal layout only knows the concrete classes TypoHeading-Formal and TypoEmphasisFormalThe factory for Smart layout only knows the concrete classes TypoHeadingSmart and TypoEmphasisSmartThe factory interface only knows about the Typo interface

  • Abstraction to the next level// A configurable document creator classpublic class DocumentCreator{TypoFactory typoFac;

    public DocumentCreator(TypoFactory typoFac){this.typoFac = typoFac;}

    public void createDocument(DocInput in) {...}}

  • Abstraction to the next levelpublic void createFormalDocument(){TypoFactory typoFac = new TypoFactoryFormalLayout();

    DocumentCreator docCre = new DocumentCreator(typoFac);

    docCre.createDocument(getDocInput());}

  • Abstraction to the next levelNote that the only thing that changes between two TypoFactory implementa-tions is the create methodWe may include concrete methods in the Typo interface making it an abstract class if it makes senseThis is known as the Factory Mehtod pattern

  • The Factory method patternProductFactorycreate()someMethod()ConcreteFactorycreate()ConcreteProduct

  • ExercisesDownload 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 createdA 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 constructorA test of the new pizza store is found in Main. Try it out! See what happens if you change the parameter to the constructorIf time permits, try to implement a third style for pizzas, including new pizza classes and a new pizza factory class

  • The Abstract FactoryOur code can now work with different concrete factories, through a Factory interfaceWhat if we need to create several types of products, not just a single type?Typo formattings of textGraphic formattings of graphic objects

  • The Abstract FactoryAnswer seems simple: just use