Design Patterns
Design Patterns
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; } }
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 } }
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.
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()); } }