Design Pattern-Factory === # 工廠模式(Factory) * 為一種創建模式 # 簡易工廠模式 * 優點 : * 簡易好上手, 常與if/else或是switch case一同使用 * 缺點 : * 如case過多維護不易,如新增類別還會動到其他程式 ## 來製作肉品吧, 先從豬肉跟牛肉兩個開始做起, 於是先有抽象出了肉 ```cpp= class meat{ public: meat(){}; ~meat(){}; void virtual make() = 0; void virtual info() = 0; string name; }; ``` ## 再來有了豬肉跟牛肉 ```cpp= class pork : public meat{ public: void make() override{ cout << "A pound of pork is made." << endl; name = "pork"; } void info() override{ cout << "It is " << name << endl; } }; class beef : public meat{ public: void make() override{ cout << "A pound of beef is made." << endl; name = "beef"; } void info() override{ cout << "It is " << name << endl; } }; ``` ## 於是建立了個簡易的工廠, 根據需要什麼肉就製作對應的肉品出來 * 簡易工廠模式如果產品越來越多會導致程式複雜化 * 試想你要一直維護一堆的if/else或是switch case光想就很複雜 * 也可以看到如果我在新增一個肌肉, Meat_Factory就需要再更動程式(違反OCP) ```cpp= enum MEAT_CODE{ MEAT_PORK = 0, MEAT_BEEF }; class Meat_Factory{ public: Meat_Factory(){}; ~Meat_Factory(){}; std::shared_ptr<meat> make(MEAT_CODE type){ if(type==MEAT_PORK){ Meat = std::make_shared<pork>(); }else{ Meat = std::make_shared<beef>(); } Meat->make(); return Meat; } private: std::shared_ptr<meat> Meat = nullptr; }; ``` # 工廠模式 * 工廠方法模式定義了一個建立物件的介面,但由子類決定要實例化的類別為何。工廠方法讓類別把 實例化 的動作推遲到了子類。 * 優點 : * 是一個高內聚的Design pattern * 滿足了OCP及SRP * 隱藏了創建對象的細節;使用者不用負擔細節,過多的細節增加了使用的成本 * 缺點 : * 如果有新的子類會有更多工廠導致程式碼日益複雜,可能會有不易理解的抽象層出現 * 原本的工廠如要擴充不易變動(舉例 : 肉要切條或是切塊) # Flow chart ![image](https://hackmd.io/_uploads/BJbrDKX70.png) ## 接續肉類的案例,於是也將工廠抽象出來如下 ```cpp= class Factory{ public: Factory(){}; virtual ~Factory(){} virtual std::shared_ptr<meat> make() = 0; }; ``` ## 並新增牛肉工廠跟豬肉工廠 ```cpp= class Pork_Factory : public Factory{ public: std::shared_ptr<meat> make() override{ product = std::make_shared<pork>(); product->make(); return product; } private: std::shared_ptr<meat> product = nullptr; }; class Beef_Factory : public Factory{ public: std::shared_ptr<meat> make() override{ product = std::make_shared<beef>(); product->make(); return product; } private: std::shared_ptr<meat> product = nullptr; }; ``` ## 今天我想要吃牛肉的話 * 創件一個Beef_Factory獲取牛肉吧 ```cpp= int main(){ // Simple Factory // Meat_Factory meat_factory; // meat_factory.make(MEAT_BEEF)->info(); // Factory Beef_Factory beef_factory; std::shared_ptr<meat> product = beef_factory.make(); product->info(); return 0; } ``` # 抽象工廠 * 優點 : * 可以確保產品之間可彼此相容 * 缺點 : * 程式會隨著須混何的產品越來越複雜 * 可用於擴展產品不同的屬性, 舉例 :法師->會火焰的法師, 可頌->鹽味可頌 # Flow chart ![image](https://hackmd.io/_uploads/HJJIDYQXR.png) ## 消費者是懶惰的,想要有先切好的肉類所以多了"形狀"的要求 * 於是有了shape的類別且有塊狀跟條狀的shape ```cpp= class shape{ public: shape(){}; ~shape(){}; string info; void virtual make() = 0; }; class stripe : public shape{ public: void make() override{ cout << "Cut into stripe" << endl; info = "stripe"; } }; class cube : public shape{ public: void make() override{ cout << "Cut into cube" << endl; info = "cube"; } }; ``` ## 於是工廠製作肉品就要選擇"肉的種類" 跟"形狀" * 於是將工廠給抽象出來 ```cpp= class Abstract_Factory{ public: virtual void make_meat() = 0; virtual void make_shape() = 0; std::shared_ptr<meat> meat_product; std::shared_ptr<shape>shape_product; }; ``` * 今天我要一個切成塊狀的牛肉就可以實踐 ```cpp= class Cube_Beef_Factory : public Abstract_Factory{ public: void make_meat(){ meat_product = std::make_shared<beef>(); meat_product->make(); } void make_shape(){ shape_product = std::make_shared<cube>(); shape_product->make(); } }; ``` * 最後輸出 ```cpp= int main(){ Cube_Beef_Factory cube_beef; cube_beef.make_meat(); cube_beef.make_shape(); cout << cube_beef.meat_product->name << endl; cout << cube_beef.shape_product->info << endl; return 0; } ``` githun : https://github.com/GU-Lin/Design_Pattern_Practice/tree/main/Creational/Factory source : https://refactoring.guru/design-patterns/factory-method https://hypc-pub.github.io/design-patterns/patterns/factory-method-pattern.html ###### tags : `Creational` `DesignPattern`