Factory Pattern PDF
Document Details
Tags
Summary
This document explains the Factory design pattern, including the Simple Factory, Factory Method, and Abstract Factory patterns. It details how to build complex objects using these patterns, focusing on situations where the code may change. The document includes example code in Java, illustrating various implementations and use cases.
Full Transcript
# Factory Pattern ## Building Complex Objects - Calling "New" is certainly coding to an implementation - In fact, it's always related to a concrete class - (Open for Modification) - That's fine when things are simple, but... ## Look Out for Change - When you have several related classes, that's...
# Factory Pattern ## Building Complex Objects - Calling "New" is certainly coding to an implementation - In fact, it's always related to a concrete class - (Open for Modification) - That's fine when things are simple, but... ## Look Out for Change - When you have several related classes, that's probably a good sign that they may change in the future ```java Duck duck; if (picnic) { duck = new MallardDuck(); } else if (hunting) { duck = new DecoyDuck(); } else if (inBathTub) { duck = new RubberDucky(); } ``` ## Design Principle - What should try to do with code that changes? ## When Building Objects is Complex - Book example: A variety of types of pizzas. - Think about constructing the weapons in your decorator lab ```java Pizza orderPizza() { Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } ``` ```java Pizza orderPizza(String type) { Pizza pizza; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("greek")) { pizza = new GreekPizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } ``` ```java Pizza orderPizza(String type) { Pizza pizza; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("greek")) { pizza = new GreekPizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("sausage")) { pizza = new SausagePizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } ``` - Encapsulate! ```java public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza; if (type.equals("cheese")) { pizza = new CheesePizza(); }else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("sausage")) { pizza = new SausagePizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; } } ``` - Now orderPizza() is tidy ```java public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type) { Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } } ``` - No new operator ## Simple Factory - Pull the code that builds the instances out and put it into a separate class - Identify the aspects of your application that vary and separate them from what stays the same ## Simple Factory Pattern A diagram is shown with 4 boxes. The left-most box is labeled "Client" with "orderProduct()" written inside. The center box is labeled "SimpleFactory" with "createProduct()" inside. The right-most box is an abstract class, and it is labeled "product" with "productMethod()" inside. From the bottom of the 'Product' box, 3 boxes branch down. Each box is a concrete implementation of the 'Product' abstract class and is called "ConcreteProductA", "ConcreteProductB", and "ConcreteProductC" ## The Factory Method - The factory method pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate - Factory method lets class defer instantiation to subclasses ## Factory Method Pattern A diagram is shown with 2 boxes. The left-most box is an abstract class, and is labeled "Product", with 'IS-A' connecting it to a box labeled "ConcreteProduct". The right-most box is an abstract class and is labeled "Creator" with 'factoryMethod()' and 'Operation()' inside. From the 'creator' box, an arrow points towards a box below it called "ConcreteCreator" with 'factoryMethod()' inside. 'IS-A' connects the 'Creator' and 'ConcreteCreator' boxes. 'HAS-A' connects the "ConcreteProduct" and "ConcreteCreator" boxes. An arrow points from the "ConcreteCreator" to the "ConcreteProduct" with 'HAS-A' written on it. - No more SimpleFactory class - Object creation is back in our class, but delegated to concrete classes ## What if There are Categories of Products? A diagram is shown with 4 boxes. An abstract class, labeled "Player" is at the top. 4 boxes extend down from "Player", 2 on the left and 2 on the right. The boxes on the left are "HeroGunner", "HeroStealth", "HeroTank", and "HeroPilot". The boxes on the right are "EnemyLevelBoss", "EnemyCaptain", and "EnemyThug", ## When Subclasses Get Out of Hand... - Make the factory an abstract class as well - Instead of subclasses for the products, subclasses for the components of the products. - The next diagram is overwhelming... breathe in, breath out ## Abstract Factory Pattern A diagram is shown with 7 boxes. Two boxes are labeled "AbstractProductA" and "AbstractProductB". The diagram also shows an abstract class called "AbstractFactory" which has 2 methods inside of it: "createProductA()" and "createProductB()". Two concrete implementations of "AbstractFactory" are shown, "ConcreteFactory1" and "ConcreteFactory2" There are 4 boxes down below representing concrete implementations of the "AbstractProductA" and "AbstractProductB" classes: "ConcreteProductA1", "ConcreteProductA2", "ConcreteProductB1", and "ConcreteProductB2". ## Abstract Factory Pattern - This design favors composition - Handy when you need to insure the quality of many similar, but slightly different versions of a class ## Summary - Simple Factory - Use when you have only 1 family of objects - Factory Method Pattern - Use when you have multiple families of objects - Abstract Factory - Use when you have multiple families of Object Components