You are on page 1of 7

The factory pattern

Encapsulating object creation


Name of new object Factory. Factories handle the details of object creation. orderPizza() and SimplePizzaFactory.createPizza(string type) Usually static method dont need to instantiate the class. Cant subclass and change the behavior of the create method.

public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(string type) { Pizza pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }

Franchising the pizza store


One approach: replace SimplePizzaFactory with three different factories, then compose the PizzaStore with the appropriate factory. o We want more control so franchises cannot employ their own process e.g. overwrite bake(). So we want to tie the PizzaStore and pizza creation together and remain flexible.

public abstract class PizzaStore { Public Pizza orderPizza(string type) { Pizza pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(string type); }

PizzaStore is now abstract, a subclass for each regional type and each subclass to make the decision about what makes up a pizza order system method should be consistent across all franchises, what varies is the style of pizzas they make. Each subclass of PizzaStore define their own createPizza() method. 1) PizzaStore.orderPizza(); (this will be the same for all franchises. 2) PizzaStore.factory.createPizza(type); (this will be specific to the pizza store). orderPizza() is defined in the abstract PizzaStore, but the concrete types are only created in the subclasses. Pizza is abstract, so orderPizza() has no idea of the concrete classes involved (decoupled). public class NYPizzaStore extends PizzaStore() { Pizza createPizza(string item) { if (item.equals(cheese)) return new NYStyleCheesePizza(); etc } }

Now each subclass takes on the responsibility of handling the instantiation of our concrete classes.

Abstract Product factoryMethod (string type) A factory method handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from the object creation code in the subclass. public abstract class Pizza { string name; string dough; string sauce; changed to: Dough dough Sauce sauce

ArrayList toppings = new ArrayList(); void prepare() { blah } void bake() { blah } void cut() { blah } void box() { blah } }

public class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza() { name = ny cheese pizza; dough = thin crust; sauce = tomato sauce; toppings.add(grated cheese); } void cut() { blah } }

The Factory Method Pattern


All factory patterns encapsulate object creation. The factory method pattern encapsulates object creation by letting subclasses decide what objects to create. The Creator classes o Abstract creator (PizzaStore) o Concrete creators (NYPizzaStore, ChicagoPizzaStore) classes that produce products. CreatePizza() is the factory method The Product classes o Factories produce products (Pizza) o Create products (NYStyleCheesePizza etc) NYPizzaStore encapsulates all the knowledge about how to make NY style pizzas. The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory method lets a class deter instantiation in subclasses. Abstract Creator an interface with a method for creating objects (the factory method). Other methods implemented in the abstract Creator are written to operate on products produced by the factory method. Only subclasses actually implement the factory method and create products. Factory method lets subclasses decide which class to instantiate because the creator class is written without knowledge of the actual products that will be created, which is decided purely by the choice of the subclass that is used. Only one ConcreteCreator decoupling implementation of the product from us. Adding additional products/changing products implementation will not affect Creator. Benefits: all creation code in one object/method, avoid code duplication and provide one place to perform maintenance. Clients depend upon the interfaces rather than the concrete classes required to instantiate the objects. Program to an interface, not an implementation, and that makes code more flexible and extensible in the future. o Factory code still uses concrete classes to instantiate real objects reality of life. So we must take control of creation code.

Object dependencies
(without OO factory) The implementation of every new kind of pizza creates another dependency for PizzaStore. Any changes to the concrete implementations of pizza affects the PizzaStore we say the PizzaStore depends on the pizza implementation.

The Dependency Inversion Principle


Design Principle Depend upon abstractions. Do not depend upon create classes. Similar to program to an interface, not an implementation. Stronger statement about abstraction high-level components should not depend on our low-level components. Write code depending on abstractions, not concrete classes. Apply the Factory Method. PizzaStore depends on Pizza (abstract class an abstraction). The concrete pizza classes depend on the Pizza abstraction too because they implement the Pizza interface in the Pizza abstract class. (not the only technique for adhering to the Dependency Inversion Principle, but one of the more powerful ones). Inversion both low-level components depend on a higher level abstraction, likewise, high-level components is also tied to the same abstraction.

To avoid OO designs that violates the Dependency Inversion Principle: No variable should hold a reference to a concrete class. No class should derive from a concrete class. No method should override an implementation.

public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); etc }

public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() { return new ThinCrustDough(); }

public Sauce createSauce() { return new ThinCrustDough(); } public Veggies[] createVeggies() { return {new Garlic(), new Onion(), new Mushroom(), new RedPepper()); } }

You might also like