日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

趣谈设计模式 | 工厂模式(Factory):利用工厂来创建对象

發布時間:2024/4/11 asp.net 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 趣谈设计模式 | 工厂模式(Factory):利用工厂来创建对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 案例:外設店鋪
  • 簡單工廠
  • 工廠方法
  • 抽象工廠
  • 總結
    • 要點
    • 三類工廠模式的特點
    • 三種工廠模式的適用場景
  • 完整代碼與文檔


工廠模式模式是創建型模式中較為常用的一個,它并不是一個模式,而是三種功能相近的設計模式的統稱,它們分別是簡單工廠模式、工廠方法模式、抽象工廠模式,下面我將結合案例來一一講解它們的特點

案例:外設店鋪

假設我們經營著一家外設店鋪,我們主要售賣雷蛇和羅技這兩個型號的鼠標,為了方便用戶購買,我們設計了一個網上購物的平臺,用戶在網上下單后我們會去根據需求來生成鼠標,再經過測試、包裝、注冊信息后,就將合格的產品發送給客戶。于是我們設計的代碼如下

我們設計了一個鼠標類,當有新型號的鼠標發布時,只需要繼承這個類即可9

class Mouse { public:virtual ~Mouse() = default;void showMessage() const{std::cout << "鼠標名:" << _name << "\n" << std::endl;}virtual void test(){std::cout << "正在對鼠標進行測試...." << std::endl;}virtual void packing(){std::cout << "正在對鼠標處理...." << std::endl;}virtual void registerItem(){std::cout << "正在注冊鼠標的商品信息...." << std::endl;} protected:std::string _name; };

我們還實現了一個店鋪類,用來處理訂單以及銷售

class PeripheralStore { public:Mouse* orderMouse(const std::string& type) //訂購鼠標{Mouse* mouse; //確定生產的型號if(type == "Logitech_G403"){mouse = new Logitech_G403;}else if(type == "Logitech_G502"){mouse = new Logitech_G502;}else if(type == "Razer_DeathAdder"){mouse = new Razer_DeathAdder;}else if(type == "Razer_Mamba"){mouse = new Razer_Mamba;}mouse->test(); //測試鼠標mouse->packing(); //包裝鼠標mouse->registerItem(); //注冊商品信息return mouse; //發貨} };

但是隨著產品的不斷迭代以及我們的銷量,我們售賣的產品時刻都會發生變化,因此我們就會經常來到這里對代碼進行修改。

我們發現,在這段代碼中我們需要改變的只有上面生產鼠標的部分,而下面對鼠標的測試、包裝、注冊都是固定的步驟,是不需要改變的,而我們將這兩者放在一起,違反了我們封閉原則,可能會因為我們生產的操作不當,影響這些固定功能的發揮。那我們要如何做呢?接下來就到工廠模式發揮作用的時候了


簡單工廠

為了將生產與產品處理分割開,我們可以構建出一個鼠標工廠類,將生產鼠標的任務委托給它,它生產完后把鼠標給我們,我們進行處理后即可銷售

鼠標工廠類實現起來很簡單,我們只需要將原來創建鼠標的代碼遷移過去即可

class MouseFactory { public:Mouse* createMouse(const std::string& type){Mouse* mouse;if(type == "Logitech_G403"){mouse = new Logitech_G403;}else if(type == "Logitech_G502"){mouse = new Logitech_G502;}else if(type == "Razer_DeathAdder"){mouse = new Razer_DeathAdder;}else if(type == "Razer_Mamba"){mouse = new Razer_Mamba;}return mouse;} };

當有了工廠之后,為了將生產任務轉交給工廠,店鋪代碼修改如下

class PeripheralStore { public:Mouse* orderMouse(const std::string& type) //訂購鼠標{Mouse* mouse;mouse = _factory.createMouse(type); //讓工廠生產鼠標mouse->test(); //測試鼠標mouse->packing(); //包裝鼠標mouse->registerItem(); //注冊商品信息return mouse; //發貨} private:MouseFactory _factory; //工廠對象,讓其來負責鼠標的生產 };

此時店鋪的類圖如下

像這樣通過工廠類創建對象,并且根據傳入的參數決定具體子類對象的做法,就是簡單工廠模式

有時候為了避免實例化工廠對象,我們會將創建對象的方法聲明為靜態的,所以簡單工廠模式又被叫做靜態工廠方法模式,但是這種方法也存在缺點,它不能通過繼承來改變創建方法的行為


工廠方法

雖然我們實現了簡單工廠模式,但是我們發現,如果我們新增或者減少鼠標的類型,我們就要去修改口罩工廠中的if-else判斷,這不符合面向對象中的開放-封閉原則,這樣對舊代碼的修改不僅容易出錯,可讀性也不好,我們拓展起來也十分麻煩,如何來優化它呢?

在上面的代碼中,一個工廠類需要負責對所有具體鼠標類的實例化,我們可以進行一個轉變,讓每個工廠只針對一種鼠標類的生產

我們可以將工廠抽象為一個接口,而為每一個鼠標型號都創建一個工廠子類,這些子類分別去實現工廠接口,如下

class IMouseFactory { public:virtual Mouse* createMouse() = 0; };class Logitech_G403_Factory : public IMouseFactory {Mouse* createMouse() override{return new Logitech_G403;} };class Razer_DeathAdder_Factory : public IMouseFactory { public:Mouse* createMouse() override{return new Razer_DeathAdder;} };

當我們需要新增一個種類的鼠標的時候,只需要繼承并實現工廠接口即可

這樣一來,我們就依靠面向對象中的多態,將每個工廠進行特化,當我們需要某一種類的鼠標時,只需要創建一個該類型的工廠并調用統一的接口,就可以得到這個類型的鼠標對象

int main() {Logitech_G403_Factory* G403_factory = new Logitech_G403_Factory;Razer_DeathAdder_Factory* DeathAdder_factory = new Razer_DeathAdder_Factory;Mouse* m1 = G403_factory->createMouse();m1->showMessage();Mouse* m2 = DeathAdder_factory->createMouse();m2->showMessage();delete m2;delete m1;delete G403_factory;delete DeathAdder_factory;return 0; }

測試結果如下

上面這種做法也就是工廠方法模式,其核心就是每一個產品都對應一個工廠之類,并利用多態特性動態創建對象

工廠方法模式定義了一個創建對象的接口,但由子類來決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類

此時的類圖如下

從類圖中可以看出,與簡單工廠方法相比,工廠方法起到了解耦合的作用,此時的無論是增加還是刪除產品,都不會對工廠接口造成影響,這樣我們程序就更具有彈性,未來想拓展產品時只需要實現接口即可。

但是在實際中,考慮到工廠方法過于復雜的問題,如果在業務邏輯十分簡單的情況下,我們沒必要使用工廠方法模式,這時使用簡單工廠模式更加簡單、方便


抽象工廠

隨著商店越做越大,我們已經不滿足于鼠標這個種類,我們想在商店中引入耳機、手柄、鍵盤等商品。但是如果我們還是使用工廠方法,那就意味著我們還需要創建耳機工廠、手柄工廠、鍵盤工廠…并且根據它們的各種型號再次派生出大量的工廠類。

為了方便舉例,這里假設每個種類的外設我們只賣一種型號 (太多了圖放不下,而且不好舉例)

如果每一個子類都對應一個工廠,那樣不僅代碼會越發繁瑣,代碼的維護也愈發艱難,所以此時就到了抽象工廠模式大展身手的時候了

我們不需要再為每一個產品分配上一個工廠,而是尋找它們之間的關聯,將它們進行分組對于上面的產品,我們可以發現主要就是雷蛇和羅技兩個品牌,所以我們可以將它們按照品牌進行分組,建立羅技工廠和雷蛇工廠

所以我們根據品牌不同,抽象出一個品牌工廠接口,它提供了生產鼠標、鍵盤、耳機的接口

class IPeripheralFactory { public: virtual ~IPeripheralFactory() = default; virtual Mouse* createMouse() = 0; virtual Earphtones* createEarPhones () = 0; virtual KeyBoard* createKeyBoard() = 0; };

接著讓雷蛇和羅技分別去實現這個接口

class LogitechFactory : public IPeripheralFactory {Mouse* createMouse() override{return new Razer_DeathAdder;}Earphtones* createEarPhones () override{return new Razer_Mako;}KeyBoard* createKeyBoard() override{return new Razer_Huntsman;} };class RazerFactory : public IPeripheralFactory {Mouse* createMouse() override{return new Logitech_G502;}Earphtones* createEarPhones () override {return new Logitech_G443;}KeyBoard* createKeyBoard() override{return new Logitech_G913;} };

下面寫一個測試程序,分別生產一個羅技鼠標和一個雷蛇鍵盤

int main() {IPeripheralFactory* logitech = new LogitechFactory; //羅技工廠IPeripheralFactory* razer = new RazerFactory; //雷蛇工廠Mouse* m1 = logitech->createMouse();m1->showMessage();KeyBoard* k1 = razer->createKeyBoard();k1->showMessage();delete k1;delete m1;delete logitech;delete razer; }

通過抽象工廠,我們就可以將產品劃分為幾個大家族

當我們想要增加新種類時(例如加入手柄),就需要到抽象工廠接口以及每一個工廠類中添加一個新的方法。

說到這有人就會疑問,那么這不是不符合開放-封閉規則嗎?確實,抽象工廠模式為了能夠實現這樣的分組,在這方面就做出了犧牲。

如果我們想對鼠標再進行一層細分,即想上面一樣分為具體的型號,那就只需要對鼠標再實現一層的簡單工廠或者工廠方法

并且我們還能發現,其實工廠方法早就以及潛伏在抽象工廠中

從上面的例子中我們可以得出,抽象工廠模式其實就是依據某個特點來將相關(依賴)的產品分組,組內不同的產品就對應同一個工廠類中的不同方法。通過這種分組就能大大減少類的數量

抽象工廠允許客戶使用抽象的接口來創建一組相關的產品,而不需要知道實際產出的產品是什么,這樣一來就使得客戶從具體的產品中被解耦


總結

要點

  • 所有的工廠模式都是用來封裝對象的創建
  • 所有工廠都通過減少應用程序和具體類之間的依賴來促進松耦合,更加具有彈性
  • 所有的工廠都是針對抽象編程而非針對具體類編程

三類工廠模式的特點

簡單工廠模式

  • 簡單工廠模式具有唯一的工廠類,通過對傳入的參數做if-else判斷來決定生產的對象

工廠方法模式

  • 工廠方法模式提供了一個工廠接口,由多個派生工廠類實現接口,利用繼承以及多態來創建不同的產品對象,避免了大量的條件判斷
  • 工廠方法將類的實例化推遲到了子類進行
  • 工廠方法中一個工廠對應著一種產品,導致類的數量過多

抽象工廠模式

  • 抽象工廠將具有關聯(依賴)的產品進行分組,并且同組中的產品由同一個工廠子類的不同方法創建,大大減少了工廠類的數量
  • 抽象工廠通過對象組合的方式維護了一個產品家族

三種工廠模式的適用場景

  • 當我們的對象創建的邏輯十分簡單,并且可以將多個對象的創建邏輯放到一個工廠類時,就沒必要大費周章,使用簡單工廠模式即可
  • 當對象創建邏輯復雜時,又或者是想將客戶代碼從具體類中解耦,又或者是我們并不知道未來還有哪些拓展的產品時,為了避免設計出一個龐大的簡單工廠,我們會將創建邏輯細分,讓每個類綁定一個工廠,這時就使用工廠方法模式
  • 當需要創建產品家族,或者想讓制造的相關產品集合起來時,就使用抽象工廠模式

  • 完整代碼與文檔

    如果有需要完整代碼或者markdown文檔的同學可以點擊下面的github鏈接
    github

    總結

    以上是生活随笔為你收集整理的趣谈设计模式 | 工厂模式(Factory):利用工厂来创建对象的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。