2019年3月1日 星期五

設計模式(4) 工廠模式(Factory Pattern)

此篇介紹GoF設計模式(Design Pattern)的其中一種—工廠模式(Factory Pattern)。


適用問題:

  試想我們要依使用者需求來實體化物件,可能會需要寫像下面這樣的code:

Pizza orderPizza(string type){
    Pizza pizza;
    if (type=="cheese"){
        pizza = new CheesePizza();
    }else if (type=="greek")
        pizza = new GreekPizza();
    }else if (type=="pepperoni"){
        pizza = new PepperoniPizza();
    }
    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();
    return pizza;
}
  基於type的輸入來決定要實體化哪種類別,但這樣的寫法在增減類別時,顯然不太符合 "closed for modification",我們要加上新口味的比薩時,又要修改此段程式增加新的if。

  比較好的寫法是我們應該要將這段實體化類別程式另外作包裝,而這也正是工廠模式的作法。




  工廠模式可以分作三種:
    1. 簡單工廠模式 Simple Factory Pattern
    2. 工廠方法模式 Factory Method Pattern
    3. 抽象工廠模式 Abstract Factory Pattern

  下面我們將依序介紹。



  簡單工廠模式例子:
    承接上面比薩的例子,我們將實體化類別的部分另外包裝成一個SimplePizzaFactory類別,裡面有createPizza()這個函式。

  PizzaSore code:比薩店實體化時要指定使用哪個SimplePizzaFactory
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;
    }
    // other methods here
}

public class SimplePizzaFactory{
    public Pizza createPizza(String type){
        Pizza pizza = null;
        if (type=="cheese"){
             pizza = new CheesePizza();
        }else if (type=="greek")
            pizza = new GreekPizza();
        }else if (type=="pepperoni"){
            pizza = new PepperoniPizza();
        }
        return pizza
    }
}


  P.S. <<Head First Design Patterns>>這本書認為簡單工廠並非Design Pattern而是一種寫程式的風格(programming idiom)。



  若我們現在想有不一樣的比薩配方呢?即我們的店有自己特色,賣的比薩有不一樣的口味。

  工廠方法模式定義:
    "The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclass." (定義一個用於建立物件的介面,讓子類決定實體化哪個類別,工廠方法使一個類別的實例化延遲到其子類別)

  工廠方法模式UML:
  工廠方法模式例子:
    建立PizzaStore再由繼承其的子類來實現factoryMethod(),如此我們要增加不同口味的比薩時就不需要修改原本的類別,只要新增類別就可。

public abstract class PizzaStore{
    public Pizza orderPizza(string type){
        Pizza pizza;
        pizza = createPizza(type);

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

        return pizza;
    }

    protected abstract createPizza(string type);
}

public class NYPizzaStore: public PizzaStore{
    Pizza createPizza(string item){
        if (type=="cheese"){
            return new NYStyleCheesePizza();
        }else if (type=="greek")
            return new NYStyleGreekPizza();
        }else if (type=="pepperoni"){
            return new NYStylePepperoniPizza();
        }else{
            return null;
        }
    }
}




  抽象工廠模式定義:
    "The Abstract Factory Pattern provides an  interface for creating families of related or dependent objects without specifying their concrete classes" (抽象工廠模式提供一個建立一系列相關或相互依賴物件的介面,而無須指定他們具體的類別)


  抽象工廠模式UML:




  參考資料:
    1. Head First Design Patterns


沒有留言:

張貼留言