Initial Scenario : We have a PizzaStore that creates different types of Pizza, Cheese, Veggie etc.
Since we can have many more varieties of pizzas in future, we can move the code for Pizza creation to Simple Factory class
public class PizzaStore {
private SimplePizzaFactory factory;
Public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderpizza(String pizzatype) {
Pizza pizza = factory.createpizza(pizzatype);
pizza.prepare();
pizza.bake();
pizza.box();
}
}
public class SimplePizzaFactory {
public Pizza createpizza(String pizzatype) {
Pizza pizza = null;
if(pizzatype.equals("veggie")) {
pizza = new VeggiePizza();
}
else if(pizzatype.equals("cheese")){
pizza = new CheesePizza();
}
return pizza;
}
}
public interface Pizza {
public void prepare();
public void bake();
public void box();
}
public class VeggiePizza implements Pizza {
//dummy code
}
public class CheesePizza implements Pizza {
//dummy code
}
public class Client1 {
public static void main(String[] args) {
SimplePizzaFactory factory = new NYPizzaFactory();
PizzaStore store = new PizzaStore(factory);
Pizza pizza = store.orderpizza("veggie");
}
}
Changed Scenario : We need to open regional branches for this PizzaStore, which will sell localized Pizzas, so we will have few more pizzas specific to the region like NYVegPizza, NYCheesePizza, ChicagoVegPizza, ChicagoCheesePizza and so on for various regions
APPROACH 1:- We can create region specific factory classes that will instantiate region specific pizzas, like NYPizzzaFactory creating NYVegPizza, NYCheesePizzas
We can continue to use the SAME PizzaStore class, just that each regional branch will initalize their respective PizzaStore with the region specific Factory
APPROACH 2: Use Factory Method Pattern
1. Create a Pizza Hierarchy : All Pizzas extend Pizza Interface
2. Define a abstract PizzaStore class with a abstract createpizza method
3. Define region subclasses for PIzzaStore that will create region specific code, basically holding the code similar to what NYPizzaFactory will be holding
public abstract class PizzaStore {
public abstract Pizza createpizza(String pizzatype);
public Pizza orderpizza(String pizzatype) {
Pizza pizza = createpizza(pizzatype);
pizza.prepare();
pizza.bake();
pizza.box();
}
}
public NYPizzaStore extends PizzaStore {
public Pizza createpizza(String pizzatype) {
Pizza pizza = null;
if(pizzatype.equals("veggie")) {
pizza = new NYVegPizza();
}
else if(pizzatype.equals("cheese")){
pizza = new NYCheesePizza();
}
return pizza;
}
}
}
public class Client2 {
public static void main(String[] args) {
PizzaStore store = new NYPizzaStore();
Pizza pizza = store.orderpizza("veggie");
}
}
DOUBTS: - Both Client1 and Client2 is has to choose either NYPizzaStore / ChicagoPizzaStore and thus becomes tightly coupled to the PizzaStore object that we create here.
Which of the 2 approaches is better, creating region specific factories or subclasses of PizzaStore
What are the advantages and disadvantages of each approach?
I hope things will be more clear to you all now.
Looking forward to having a good discussion to appreciate this pattern