Factory Method Pattern

The Factory Method Pattern defines an interface for creating an object, but lets subclasses decides which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Factory Method Pattern Diagram

Implemtation

Creating a Creator interface:

public abstract class PizzaStore {
 
	/* factory method for concrete creators */
	abstract Pizza createPizza(String item);
	
	/* Every franchise has the same process of ordering pizza */
	public Pizza orderPizza(String type) {
		Pizza pizza = createPizza(type);
		System.out.println("--- Making a " + pizza.getName() + " ---");
		
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		
		return pizza;
	}
}

Creating a Concrete Creator:

public class NYPizzaStore extends PizzaStore {
	/* Implementing factory method so each franchise can have its own stype of pizza */
	Pizza createPizza(String item) {
		/* concrete products */
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleVeggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		} else return null;
		}
 
}

Creating a Product:

public abstract class Pizza {
	String name;
	String dough;
	String sauce;
	ArrayList<String> toppings = new ArrayList<String>();
 
	void prepare() {
		System.out.println("Prepare " + name);
		
		System.out.println("Tossing dough...");
		
		System.out.println("Adding sauce...");
		
		System.out.println("Adding toppings: ");
 
		for (String topping : toppings) {
			System.out.println(" " + topping);
		}
	}
 
	void bake() {
		System.out.println("Bake for 25 minutes at 350");
	}
 
	void cut() {
		System.out.println("Cut the pizza into diagonal slices");
	}
 
	void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}
 
	public String getName() {
		return name;
	}
 
	public String toString() {
		StringBuffer display = new StringBuffer();
		display.append("---- " + name + " ----\n");
		display.append(dough + "\n");
		display.append(sauce + "\n");
		
		for (String topping : toppings) {
			display.append(topping + "\n");
		}
		return display.toString();
	}
 
}
 

Creating Concrete Products:

public class NYStyleCheesePizza extends Pizza {
	public NYStyleCheesePizza() {
		name = "NY Style Sauce and Cheese Pizza";
		dough = "Thin Crust Dough";
		sauce = "Marinara Sauce";
		toppings.add("Grated Reggiano Cheese");
	}
}

Testing:

public class PizzaTestDrive {
	public static void main(String[] args) {
		PizzaStore nyStore = new NYPizzaStore();	
		PizzaStore chicagoStore = new ChicagoPizzaStore();
	
		Pizza pizza = nyStore.orderPizza("cheese");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
		pizza = chicagoStore.orderPizza("cheese");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");
		
		pizza = nyStore.orderPizza("clam");
		System.out.println("Ethan ordered a " + pizza.getName() + "\n");
		pizza = chicagoStore.orderPizza("clam");
		System.out.println("Joel ordered a " + pizza.getName() + "\n");
	}
}