Factory Pattern

Let's say..

you have a pizza shop and you have many kinds of pizza such cheese pizza, veggie pizza and so on. You design like this.

  PizzaStore
order()
                 Pizza
prepare()
bake()
cut()
box()
CheesePizza
VeggiePizza
Clam Pizza

Or you might code like this in order pizza function...

When you want to add or extend remove type of pizza, you need to modify more conditions. 

Problem..

Solution...

Base code should be enclosed for for modifications and can be extended by concrete class so we should encapsulate the part that varies to one class called "Simple Factory" class.

public class SimplePizzaFactory{
    public Pizza createPizza(String type){
        Pizza pizza = null;

       if(type.equals("cheese")){
            pizza = new CheesePizza();
       }
       else if(type.equals("pepperon")){
            pizza = new PepperonPizza();
       }
       else if(type.equals("veggie")){
            pizza = new VeggiePizza();
       }
       return pizza;
    }
}

Encapsulate createPizza in SimplePizzaFactory that accepts type of pizza.

So we can call factory's function and pass the type of pizza. Any modifications in factory class will not affect the base code.

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;
    } 
}

Diagrams

  PizzaStore
order()
                 Pizza
prepare()
bake()
cut()
box()
CheesePizza
VeggiePizza
Clam Pizza
SimplePizzaFactory
createPizza()

Simple Factory Pattern

is an interface for creating objects without exposing the object creation logic to the client.

Recap

DEMO

Let's say..

If you use simple factory....

NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("veggie");

chicagoPizzaFactory chicagoFactory = new chicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoFactory.orderPizza("veggie");

Problem

Many factory class to instantiate each of pizza class

Solution..

Using abstract factory pattern, you can tie store and factory together but it is still flexible so move factory object to abstract method in PizzaStore.

 

How to do

Remove those factory classes and implement createPizza method in PizzaStore by using abstract method. Implement createPizza in children classes extended from PizzaStore.

 

 

        PizzaStore
orderPizza()
abstract createPizza()
 
    NYStylePizzaStore
createPizza()
 
  ChicagoStylePizzaStore
createPizza()
 

Extends PizzaStore

In code..

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;

        pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    } 

    abstract createPizza(String type);
}
public class NYPizzaStore extends PizzaStore{
    public Pizza createPizza(String type){
        Pizza pizza = null;

       if(type.equals("cheese")){
            pizza = new NYCheesePizza();
       }
       else if(type.equals("pepperon")){
            pizza = new NYPepperonPizza();
       }
       else if(type.equals("veggie")){
            pizza = new NYVeggiePizza();
       }
       return pizza;
    }
}

 The subclass gets to determine which pizza is made and call sub-classes of pizza based on its type.

public class ChicagoPizzaStore extends PizzaStore{
    public Pizza createPizza(String type){
        Pizza pizza = null;

       if(type.equals("cheese")){
            pizza = new ChicagoCheesePizza();
       }
       else if(type.equals("pepperon")){
            pizza = new ChicagoPepperonPizza();
       }
       else if(type.equals("veggie")){
            pizza = new ChicagoVeggiePizza();
       }
       return pizza;
    }
}

How to instantiate

PizzaStore nyPizzaStore = new NYPizzaStore();
nyPizzaStoreStore.orderPizza("veggie");

PizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
chicagoPizzaStore.orderPizza("veggie");

Diagrams

Compare

PizzaStore nyPizzaStore = new NYPizzaStore();
nyPizzaStoreStore.orderPizza("veggie");

PizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
chicagoPizzaStore.orderPizza("veggie");
NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("veggie");

chicagoPizzaFactory chicagoFactory = new chicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoFactory.orderPizza("veggie");

Using Abstract Factory

Using Simple Factory

Abstract Factory Pattern

is an abstract factory is an interface to create of related objects without specifying/exposing their classes.

Advantages

Recap

The factory method pattern is useful if you have only got one concrete creator because you are decoupling the implementations of the product from its use. If you add additional products or change a product's implementation, it will not affect your creator.

DEMO

Factory Pattern

By Sofwan Abdulwahab

Factory Pattern

  • 214