C++設計模式編程中簡單工廠與工廠方法模式的實例對比
簡單工廠模式實例
題目:實現(xiàn)計算器的輸入2個數(shù)和運算符,得到結果
工程結構:
(1)頭文件
COperationFactory.h(運算符工廠類)
(2)源文件
SimpleFactory.cpp(客戶端應用類,主函數(shù)所在)
(3)運算類
COperation.cpp(運算符基類)
COperation.h
COperationAdd.h(加法運算符子類,繼承于COperation)
COperationDiv.h (除法運算符子類,繼承于COperation)
COperationMul.h (乘法運算符子類,繼承于COperation)
COperationSub.h(減法運算符子類,繼承于COperation)
============= 代碼實現(xiàn)部分 =============
COperationFactory.h(運算符工廠類)
/************************************************************************/ /* 運算符工廠類 */ /************************************************************************/ #ifndef _OPERATION_FACTORY_H_ #define _OPERATION_FACTORY_H_ #include "stdafx.h" #include "COperation.h" #include "COperationAdd.h" #include "COperationSub.h" #include "COperationMul.h" #include "COperationDiv.h" #include "COperationFactory.h" class COperationFactory { public: COperationFactory(){}; ~COperationFactory(){}; // 根據(jù)入?yún)⒌牟煌?,?chuàng)建其對應的運算符類指針。就像是個工廠,創(chuàng)建用戶指定的運算符類指針 static COperation* NewOperation(const string& strOperate) { // 入?yún)⒑戏ㄐ耘袛?,防止后面的strOperate[0]發(fā)生越界訪問 if (strOperate.size() != 1) { return NULL; } COperation* pOperation = NULL; switch (strOperate[0]) { case '+': pOperation = new COperationAdd(); break; case '-': pOperation = new COperationSub(); break; case '*': pOperation = new COperationMul(); break; case '/': pOperation = new COperationDiv(); break; default: break; } return pOperation; }; }; #endif _OPERATION_FACTORY_H_
COperation.cpp(運算符基類)
#include "stdafx.h" #include "COperation.h" COperation::COperation() : _dNumA(0) , _dNumB(0) { }
COperation.h
/************************************************************************/ /* 運算符基類 */ /************************************************************************/ #ifndef _COPERATION_H_ #define _COPERATION_H_ class COperation { public: COperation(); ~COperation(){}; // 設置被運算數(shù) void SetNumA(double dNumA) { _dNumA = dNumA; }; // 獲取被運算數(shù) double GetNumA() { return _dNumA; }; // 設置運算數(shù) void SetNumB(double dNumB) { _dNumB = dNumB; }; // 獲取運算數(shù) double GetNumB() { return _dNumB; }; // 計算結果且在子類中實現(xiàn)各自的運算方法結果 virtual double Result() { double dResult = 0; return dResult; } private: double _dNumA; double _dNumB; }; #endif _COPERATION_H_
COperationAdd.h(加法運算符子類,繼承于COperation)
/************************************************************************/ /* 加法運算符子類,繼承于運算符基類 */ /************************************************************************/ #ifndef _COPERATION_ADD_H_ #define _COPERATION_ADD_H_ #include "COperation.h" class COperationAdd : public COperation { public: COperationAdd(){}; ~COperationAdd(){}; double Result() { return (GetNumA() + GetNumB()); }; }; #endif _COPERATION_ADD_H_
COperationDiv.h (除法運算符子類,繼承于COperation)
/************************************************************************/ /* 除法運算符子類,繼承于運算符基類 */ /************************************************************************/ #ifndef _COPERATION_DIV_H_ #define _COPERATION_DIV_H_ #include "COperation.h" class COperationDiv : public COperation { public: COperationDiv(){}; ~COperationDiv(){}; double Result() { double dResult = 0; if (0 != GetNumB()) { dResult = (GetNumA() / GetNumB()); } else { cout << "error: divisor is "; } return dResult; }; }; #endif _COPERATION_DIV_H_
COperationMul.h (乘法運算符子類,繼承于COperation)
/************************************************************************/ /* 乘法運算符子類,繼承于運算符基類 */ /************************************************************************/ #ifndef _COPERATION_MUL_H_ #define _COPERATION_MUL_H_ #include "COperation.h" class COperationMul : public COperation { public: COperationMul(){}; ~COperationMul(){}; double Result() { return (GetNumA() * GetNumB()); }; }; #endif _COPERATION_MUL_H_
COperationSub.h(減法運算符子類,繼承于COperation)
/************************************************************************/ /* 減法運算符子類,繼承于運算符基類 */ /************************************************************************/ #ifndef _COPERATION_SUB_H_ #define _COPERATION_SUB_H_ #include "COperation.h" class COperationSub : public COperation { public: COperationSub(){}; ~COperationSub(){}; double Result() { return (GetNumA() - GetNumB()); }; }; #endif _COPERATION_SUB_H_
SimpleFactory.cpp(客戶端應用類,主函數(shù)所在)
// SimpleFactory.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include "COperationFactory.h" int _tmain(int argc, _TCHAR* argv[]) { // 通過運算符工廠創(chuàng)建加法運算 COperation* OperAdd = COperationFactory::NewOperation("+"); if (NULL != OperAdd) { OperAdd->SetNumA(168); // 設置被加數(shù) OperAdd->SetNumB(105); // 設置加數(shù) cout << "168 + 105 = " << (OperAdd->Result()) << endl; } // 通過運算符工廠創(chuàng)建減法運算 COperation* OperSub = COperationFactory::NewOperation("-"); if (NULL != OperSub) { OperSub->SetNumA(168); // 設置被減數(shù) OperSub->SetNumB(105); // 設置減數(shù) cout << "168 - 105 = " << (OperSub->Result()) << endl; } // 通過運算符工廠創(chuàng)建乘法運算 COperation* OperMul = COperationFactory::NewOperation("*"); if (NULL != OperMul) { OperMul->SetNumA(168); // 設置被乘數(shù) OperMul->SetNumB(105); // 設置乘數(shù) cout << "168 * 105 = " << (OperMul->Result()) << endl; } // 通過運算符工廠創(chuàng)建除法運算 COperation* OperDiv = COperationFactory::NewOperation("/"); if (NULL != OperDiv) { OperDiv->SetNumA(168); // 設置被除數(shù) OperDiv->SetNumB(105); // 設置除數(shù) cout << "168 / 105 = " << (OperDiv->Result()) << endl; OperDiv->SetNumB(0); // 改變除數(shù) cout << (OperDiv->Result()) << endl; } // 阻止控制臺進程結束,便于查看結果 int nEnd = 0; cin >> nEnd; return 0; }
抽象工廠模式實例
工程結構:
(1)抽象產(chǎn)品類
IFruit.h
(2)抽象工廠類
IFruitGardener.h
(3)具體產(chǎn)品類
CApple.h
CGrape.h
CStrawberry.h
(4)具體工廠類
CAppleGardener.h
CGrapeGardener.h
CStrawberryGardener.h
(5)客戶端
FactoryMethodApplication.cpp
(1)抽象產(chǎn)品類
IFruit.h
/************************************************************************/ /* 抽象水果類(abstract Product) */ /************************************************************************/ #ifndef _IFRUIT_H_ #define _IFRUIT_H_ #include <string> #include <iostream> using namespace std; class IFruit { public: virtual void grow() = 0; virtual void harvest() = 0; virtual void plant() = 0; }; #endif _IFRUIT_H_
(2)抽象工廠類
IFruitGardener.h
/************************************************************************/ /* 抽象水果園丁類(abstract Factory) */ /************************************************************************/ #ifndef _IFRUIT_GARDENER_H_ #define _IFRUIT_GARDENER_H_ #include "IFruit.h" class IFruitGardener { public: virtual IFruit* Factory() = 0; }; #endif _IFRUIT_GARDENER_H_
(3)具體產(chǎn)品類
CApple.h
/************************************************************************/ /* 具體的蘋果類(Concrete Product) */ /************************************************************************/ #ifndef _APPLE_H_ #define _APPLE_H_ #include "IFruit.h" class CApple : public IFruit { public: void grow() { cout << "Apple is growing..." << endl; }; void harvest() { cout << "Apple has been harvested." << endl; }; void plant() { cout << "Apple has been planted." << endl; }; int GetTreeAge() { return m_iAppleTreeAge; }; void SetTreeAge(const int iAge) { m_iAppleTreeAge = iAge; } private: int m_iAppleTreeAge; }; #endif _APPLE_H_
CGrape.h
/************************************************************************/ /* 具體的葡萄類(Concrete Product) */ /************************************************************************/ #ifndef _GRAPE_H_ #define _GRAPE_H_ #include "IFruit.h" class CGrape : public IFruit { public: void grow() { cout << "Grape is growing..." << endl; }; void harvest() { cout << "Grape has been harvested." << endl; }; void plant() { cout << "Grape has been planted." << endl; }; bool GetSeedless() { return m_bSeedless; }; void SetSeedless(const bool bSeedless) { m_bSeedless = bSeedless; }; private: bool m_bSeedless; }; #endif _GRAPE_H_
CStrawberry.h
/************************************************************************/ /* 具體的草莓類(Concrete Product) */ /************************************************************************/ #ifndef _STRAWBERRY_H_ #define _STRAWBERRY_H_ #include "IFruit.h" class CStrawberry : public IFruit { public: void grow() { cout << "Strawberry is growing..." << endl; }; void harvest() { cout << "Strawberry has been harvested." << endl; }; void plant() { cout << "Strawberry has been planted." << endl; }; }; #endif _STRAWBERRY_H_
(4)具體工廠類
CAppleGardener.h
/************************************************************************/ /* 具體的蘋果園丁類(Concrete Factory) */ /************************************************************************/ #ifndef _APPLE_GARDENER_H_ #define _APPLE_GARDENER_H_ #include "IFruitGardener.h" #include "CApple.h" class CAppleGardener : public IFruitGardener { public: CAppleGardener():m_pApple(NULL){}; IFruit* Factory() { if (NULL == m_pApple) { m_pApple = new CApple(); } return m_pApple; }; private: CApple* m_pApple; }; #endif _APPLE_GARDENER_H_
CGrapeGardener.h
/************************************************************************/ /* 具體的葡萄園丁類(Concrete Factory) */ /************************************************************************/ #ifndef _GRAPE_GARDENER_H_ #define _GRAPE_GARDENER_H_ #include "IFruitGardener.h" #include "CGrape.h" class CGrapeGardener : public IFruitGardener { public: CGrapeGardener():m_pGrape(NULL){}; IFruit* Factory() { if (NULL == m_pGrape) { m_pGrape = new CGrape(); } return m_pGrape; }; private: CGrape* m_pGrape; }; #endif _GRAPE_GARDENER_H_
CStrawberryGardener.h
/************************************************************************/ /* 具體的草莓園丁類(Concrete Factory) */ /************************************************************************/ #ifndef _STRAWBERRY_GARDENER_H_ #define _STRAWBERRY_GARDENER_H_ #include "IFruitGardener.h" #include "CStrawberry.h" class CStrawberryGardener : public IFruitGardener { public: CStrawberryGardener():m_pStrawberry(NULL){}; IFruit* Factory() { if (NULL == m_pStrawberry) { m_pStrawberry = new CStrawberry(); } return m_pStrawberry; }; private: CStrawberry* m_pStrawberry; }; #endif _STRAWBERRY_GARDENER_H_
(5)客戶端
FactoryMethodApplication.cpp
// FactoryMethodApplication.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include <Windows.h> #include "IFruitGardener.h" #include "CAppleGardener.h" #include "CGrapeGardener.h" #include "CStrawberryGardener.h" int _tmain(int argc, _TCHAR* argv[]) { static IFruitGardener* pFruitFactory1 = NULL; static IFruitGardener* pFruitFactory2 = NULL; static IFruit* pFruit1 = NULL; static IFruit* pFruit2 = NULL; pFruitFactory1 = new CAppleGardener(); if (NULL != pFruitFactory1) { pFruit1 = pFruitFactory1->Factory(); if (NULL != pFruit1) { pFruit1->grow(); pFruit1->harvest(); pFruit1->plant(); } } pFruitFactory2 = new CGrapeGardener(); if (NULL != pFruitFactory2) { pFruit2 = pFruitFactory2->Factory(); if (NULL != pFruit2) { pFruit2->grow(); pFruit2->harvest(); pFruit2->plant(); } } Sleep(10000); return 0; }
總結
首先無論是簡單工廠模式還是工廠方法模式都是把不變的地方提取出來,把容易發(fā)生變化的封裝起來。以達到做大程度的復用,和適應用戶的變動,以及項目的擴展。
一、簡單工廠模式
1.理解
又稱為靜態(tài)工廠模式,它專門定義一個類來負責創(chuàng)建其他類的實例,被創(chuàng)建的實例通常都具有相通的父類。由工廠類根據(jù)傳入的參數(shù)動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類的實例。它包含必要的判斷邏輯,能根據(jù)外界給定的信息,決定應該穿件那個具體類的對象。簡單工廠模式可以理解為父親給兒子留了一筆錢,規(guī)定這筆錢可以用于上學、買房或者買車,然后讓兒子自己選擇用于哪一個。
2.優(yōu)點
工廠類包含必要的邏輯判斷,可以決定在什么時候創(chuàng)建哪一個類的實例,客戶端可以避免直接創(chuàng)建對象。這樣就可以實現(xiàn)對責任的分割,降低耦合性,明確了具體的職責和權力,有利于整個系統(tǒng)的優(yōu)化。
3.缺點
當產(chǎn)品具有比較復雜的多層結構時,它的工廠類只有一個,這時候再以不變應萬變就成為它最大的缺點了。因為工廠類是整個組織的核心,它聚集了所有產(chǎn)品的創(chuàng)建邏輯,一旦工廠不能正常工作,整個系統(tǒng)都會受到影響,可擴展性較差。擴展性差一旦有新的需求,就不得不修改工廠邏輯,這樣就會導致工廠邏輯過為復雜,違背了開——閉原則。同時靜態(tài)工廠方法不利于形成基于繼承的等級結構。
二、工廠方法模式
1.理解
它是一個粒度很小的設計模式,因為模式的表現(xiàn)只是一個抽象的方法。工廠方法模式定義了一個用于創(chuàng)建對象的界面,讓子類決定具體實例化哪一個類。也就是在工廠和產(chǎn)品之間增加界面,工廠不再負責產(chǎn)品的實現(xiàn),有借口針對不同條件返回不同的類實例,再由具體類實例去實現(xiàn)。工廠方法時簡單工廠的衍生,改進了許多簡單工廠的缺點,遵循了開——閉原則,實現(xiàn)了可擴展,可以用于更為復雜的產(chǎn)品結果場合。工廠方法可以理解為同樣是父親給兒子留了一筆錢,然后直接讓兒子去支配,怎么花父親一律不管。
2.優(yōu)點
工廠方法模式客服了簡單工廠的很多缺點,它每個具體工廠只完成單一任務,而且遵循開——閉原則,代碼簡潔而且具有良好的擴展性。
3.缺點
如果有產(chǎn)品類需要修改,對應的工廠類也需要進行修改。一旦有多個產(chǎn)品類都需要修改的時候,對號入座的問題就出現(xiàn)了,這是對工廠類的修改就會變得相當復雜。因此工廠方法模式雖然有利于擴展但是不利于維護。
綜上所述,我們就可以知道針對不同的情況具體采用哪種模式對編程更有利了。當需要創(chuàng)建的對象比較少,客戶只知道傳入工廠的參數(shù),并不關心如何創(chuàng)建對象的時候就可以采用簡單工廠模式;當類將創(chuàng)建對象的職責委托給多個幫助子類中的某一個時就可以采用工廠方法模式了。
相關文章
OpenMP task construct 實現(xiàn)原理及源碼示例解析
這篇文章主要為大家介紹了OpenMP task construct 實現(xiàn)原理及源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03C++中類的三種訪問權限解析:private、public與protect
這篇文章主要介紹了C++中類的三種訪問權限解析:private、public與protect,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11