設計模式——工廠方法模式

《Head First 設計模式》 學習筆記,碼雲同步更新中

如有錯誤或不足之處,請一定指出,謝謝~

往期回顧

  1. 設計模式——策略模式
  2. 設計模式——裝飾者模式
  3. 設計模式——觀察者模式
  4. 設計模式——簡單工廠
  5. 設計模式——工廠方法模式

工廠方法模式(Factory Method Pattern)

  • 定義:
    • 工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。
      工廠方法讓類把實例化推遲到子類。
  • 結構:
    • Factory:抽象工廠
    • ConcreteFactory:具體工廠
    • Product:抽象產品
    • ConcreteProduct:具體產品
  • 對比簡單工廠:
    • 簡單工廠將對象的創建邏輯寫在工廠類裏,那麼當我們有新的對象加入時,
      就需要修改工廠類的代碼。這不符合開閉原則。那如果我們定義一個抽象工廠類,
      然後將具體的對象創建過程交給子類去做,當我們引進新的產品時,
      只需要增加一個新的工廠類即可。顯然這是要優於簡單工廠模式的,
      這就是我們所說的工廠方法模式。
  • 優點:
    • 隱藏產品具體實現,用戶只關心工廠,無需關心細節。
    • 有新產品加入時,無需修改其他工廠和產品,只需添加新的工廠和產品。擴展性良好,完全符合“開閉原則”。
    • 可結合配置文件實現對象實例化時的動態指定。
  • 缺點:
    • 會給系統帶來更多的類,增加複雜度和額外開銷。
  • 案例:
    • 先看上一節的簡單工廠:顧客點單時,需要根據菜名創建出各種不同種類的披薩。
      這些披薩都源自同一個披薩基類,不過各自有自己的口味實現。
      而我們創建具體的披薩對象時,只需要提供名字,不需要知道它們是如何創建的。
      這時就可以用到簡單工廠,傳遞一個參數給工廠類,返回一個相應的披薩對象。
    • 這時我們披薩店要擴張了,但在各個省可能會有不同的製作方法。
      我們希望披薩在披薩口味上加盟店有自己的決定權。
      但在製作流程上要受到總店的控制,
      比如必須使用我們品牌的盒子來裝披薩等等。
  • 代碼:
/**
 * 披薩店超類
 **/
public abstract class PizzaStore {

    public Pizza orderPizza(String type) {

        // 把創建披薩方法從簡單工廠拿回來
        Pizza pizza = createPizza(type);

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

        return pizza;
    }

    /**
     * 將實例化披薩的責任移到抽象方法中,這個方法就等同於一個工廠
     * 子類通過這個方法來執行對象實例化邏輯,達到超類和子類解耦的目的
     */
    abstract Pizza createPizza(String type);

}

/**
 * 上海加盟店
 **/
public class SHPizzaStore extends PizzaStore {
    @Override
    protected Pizza createPizza(String type) {
        if (type.equals("cheese")) {
            return new SHCheesePizza();
        } else if (type.equals("veggie")) {
            return new SHVeggiePizza();
        }
        return null;
    }
}

// 其他加盟店略

/**
 * 披薩超類
 **/
public interface Pizza {
    /**
     * 準備
     */
    void prepare();

    /**
     * 烘焙
     */
    void bake();

    /**
     * 切片
     */
    void cut();

    /**
     * 裝盒
     */
    void box();
}

/**
 * 上海芝士披薩
 **/
public class SHCheesePizza implements Pizza{

    @Override
    public void prepare() {
    }

    @Override
    public void bake() {
    }

    @Override
    public void cut() {
    }

    @Override
    public void box() {
        System.out.println("上海風味芝士披薩完成...");
    }
}

// 其他種類披薩略

/**
 * 測試類
 **/
public class Test {
    public static void main(String[] args) {
        // 首先需要一個上海披薩店
        SHPizzaStore shPizzaStore = new SHPizzaStore();
        // 然後點單
        Pizza pizza = shPizzaStore.orderPizza("cheese");
    }
}

結果:
    上海風味芝士披薩完成...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章