Total Pageviews

2017/01/09

[Design Pattern] Factory Pattern

Assume I have a juice store, which provide apple juice, orange juice and kiwi juice. As I accept customer's order, I will make juice and deliver juice to customer.

Therefore, I will do make juice and deliver juice no matter which juices are ordered.
package albert.practice.designpattern.factory;

public interface Juice {
    void makeJuice();
    void deliverJuice();
}


Each juice will implement Juice interface, and implement its own logic in each class.
Here is apple juice:

package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AppleJuice implements Juice {

    @Override
    public void makeJuice() {
      log.debug("making APPLE juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver APPLE juice to customer.");
    }

}



Here is orange juice:

package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OrangeJuice implements Juice {

    @Override
    public void makeJuice() {
        log.debug("making ORANGE juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver ORANGE juice to customer.");        
    }

}



Here is kiwi juice:
package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class KiwiJuice implements Juice {

    @Override
    public void makeJuice() {
        log.debug("making KIWI juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver KIWI juice to customer.");        
    }

}


I also create a fruit enumeration to tell which juice I will make:
package albert.practice.designpattern.factory;

public enum FruitEnum {
    APPLE, ORANGE, KIWI;
}


And I create a JuiceStore to process customers' order. The processOrder method is used to create apple, orange or kiwi object depends on customer's order.
package albert.practice.designpattern.factory;

public class JuiceStore {

    public static void main(String[] args) {
        JuiceStore test = new JuiceStore();
        test.processOrder(FruitEnum.KIWI);
        test.processOrder(FruitEnum.APPLE);
        test.processOrder(FruitEnum.ORANGE);
    }

    public void processOrder(FruitEnum fruit) {
        Juice juice = null;
        if (FruitEnum.APPLE == fruit) {
            juice = new AppleJuice();
        } else if (FruitEnum.ORANGE == fruit) {
            juice = new OrangeJuice();
        } else if (FruitEnum.KIWI == fruit) {
            juice = new KiwiJuice();
        }
        juice.makeJuice();
        juice.deliverJuice();
    }

}


It seems good so far. But if we would like to create object without exposing the if-else creating logic to client, we need to apply factory pattern to refactor the existing architecture.


Therefore, we need to create a JuiceFactory to generate object of concrete class based on given fruit.
package albert.practice.designpattern.factory;

public class JuiceFactory {

    public Juice getJuice(FruitEnum fruitEnum) {
        Juice juice = null;
        if (FruitEnum.APPLE == fruitEnum) {
            juice = new AppleJuice();
        } else if (FruitEnum.ORANGE == fruitEnum) {
            juice = new OrangeJuice();
        } else if (FruitEnum.KIWI == fruitEnum) {
            juice = new KiwiJuice();
        }
        return juice;
    }

}



We can see the updated JuiceStore class, the creating logic had been hide in JuiceFactory, we only need to tell JuiceFactory which fruit I would like to make:

package albert.practice.designpattern.factory;

public class JuiceStore {

    public static void main(String[] args) {
        JuiceFactory factory = new JuiceFactory();
        
        Juice apple = factory.getJuice(FruitEnum.APPLE);
        apple.makeJuice();
        apple.deliverJuice();
        
        Juice orange = factory.getJuice(FruitEnum.ORANGE);
        orange.makeJuice();
        orange.deliverJuice();
        
        Juice kiwi = factory.getJuice(FruitEnum.KIWI);
        kiwi.makeJuice();
        kiwi.deliverJuice();
    }
}


We can see JuiceStore asks JuiceFactory to create object based on its demands, and JuiceStore will use its object to make juice and deliver juice.




No comments: