簡單工廠模式實例
題目:實現計算器的輸入2個數和運算符,得到結果
工程結構:
(1)頭文件
COperationFactory.h(運算符工廠類)
(2)源文件
SimpleFactory.cpp(客戶端應用類,主函數所在)
(3)運算類
COperation.cpp(運算符基類)
COperation.h
COperationAdd.h(加法運算符子類,繼承于COperation)
COperationDiv.h (除法運算符子類,繼承于COperation)
COperationMul.h (乘法運算符子類,繼承于COperation)
COperationSub.h(減法運算符子類,繼承于COperation)
============= 代碼實現部分 =============
COperationFactory.h(運算符工廠類)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
/************************************************************************/ /* 運算符工廠類 */ /************************************************************************/ #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(){}; // 根據入參的不同,創建其對應的運算符類指針。就像是個工廠,創建用戶指定的運算符類指針 static COperation* NewOperation( const string& strOperate) { // 入參合法性判斷,防止后面的strOperate[0]發生越界訪問 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(運算符基類)
1
2
3
4
5
6
7
8
9
|
#include "stdafx.h" #include "COperation.h" COperation::COperation() : _dNumA(0) , _dNumB(0) { } |
COperation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
/************************************************************************/ /* 運算符基類 */ /************************************************************************/ #ifndef _COPERATION_H_ #define _COPERATION_H_ class COperation { public : COperation(); ~COperation(){}; // 設置被運算數 void SetNumA( double dNumA) { _dNumA = dNumA; }; // 獲取被運算數 double GetNumA() { return _dNumA; }; // 設置運算數 void SetNumB( double dNumB) { _dNumB = dNumB; }; // 獲取運算數 double GetNumB() { return _dNumB; }; // 計算結果且在子類中實現各自的運算方法結果 virtual double Result() { double dResult = 0; return dResult; } private : double _dNumA; double _dNumB; }; #endif _COPERATION_H_ |
COperationAdd.h(加法運算符子類,繼承于COperation)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/************************************************************************/ /* 加法運算符子類,繼承于運算符基類 */ /************************************************************************/ #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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/************************************************************************/ /* 除法運算符子類,繼承于運算符基類 */ /************************************************************************/ #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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/************************************************************************/ /* 乘法運算符子類,繼承于運算符基類 */ /************************************************************************/ #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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/************************************************************************/ /* 減法運算符子類,繼承于運算符基類 */ /************************************************************************/ #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(客戶端應用類,主函數所在)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// SimpleFactory.cpp : 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include "COperationFactory.h" int _tmain( int argc, _TCHAR* argv[]) { // 通過運算符工廠創建加法運算 COperation* OperAdd = COperationFactory::NewOperation( "+" ); if (NULL != OperAdd) { OperAdd->SetNumA(168); // 設置被加數 OperAdd->SetNumB(105); // 設置加數 cout << "168 + 105 = " << (OperAdd->Result()) << endl; } // 通過運算符工廠創建減法運算 COperation* OperSub = COperationFactory::NewOperation( "-" ); if (NULL != OperSub) { OperSub->SetNumA(168); // 設置被減數 OperSub->SetNumB(105); // 設置減數 cout << "168 - 105 = " << (OperSub->Result()) << endl; } // 通過運算符工廠創建乘法運算 COperation* OperMul = COperationFactory::NewOperation( "*" ); if (NULL != OperMul) { OperMul->SetNumA(168); // 設置被乘數 OperMul->SetNumB(105); // 設置乘數 cout << "168 * 105 = " << (OperMul->Result()) << endl; } // 通過運算符工廠創建除法運算 COperation* OperDiv = COperationFactory::NewOperation( "/" ); if (NULL != OperDiv) { OperDiv->SetNumA(168); // 設置被除數 OperDiv->SetNumB(105); // 設置除數 cout << "168 / 105 = " << (OperDiv->Result()) << endl; OperDiv->SetNumB(0); // 改變除數 cout << (OperDiv->Result()) << endl; } // 阻止控制臺進程結束,便于查看結果 int nEnd = 0; cin >> nEnd; return 0; } |
抽象工廠模式實例
工程結構:
(1)抽象產品類
IFruit.h
(2)抽象工廠類
IFruitGardener.h
(3)具體產品類
CApple.h
CGrape.h
CStrawberry.h
(4)具體工廠類
CAppleGardener.h
CGrapeGardener.h
CStrawberryGardener.h
(5)客戶端
FactoryMethodApplication.cpp
(1)抽象產品類
IFruit.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/************************************************************************/ /* 抽象水果類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/************************************************************************/ /* 抽象水果園丁類(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)具體產品類
CApple.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/************************************************************************/ /* 具體的蘋果類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/************************************************************************/ /* 具體的葡萄類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/************************************************************************/ /* 具體的草莓類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/************************************************************************/ /* 具體的蘋果園丁類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/************************************************************************/ /* 具體的葡萄園丁類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/************************************************************************/ /* 具體的草莓園丁類(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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
// 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; } |
總結
首先無論是簡單工廠模式還是工廠方法模式都是把不變的地方提取出來,把容易發生變化的封裝起來。以達到做大程度的復用,和適應用戶的變動,以及項目的擴展。
一、簡單工廠模式
1.理解
又稱為靜態工廠模式,它專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有相通的父類。由工廠類根據傳入的參數動態決定應該創建哪一個產品類的實例。它包含必要的判斷邏輯,能根據外界給定的信息,決定應該穿件那個具體類的對象。簡單工廠模式可以理解為父親給兒子留了一筆錢,規定這筆錢可以用于上學、買房或者買車,然后讓兒子自己選擇用于哪一個。
2.優點
工廠類包含必要的邏輯判斷,可以決定在什么時候創建哪一個類的實例,客戶端可以避免直接創建對象。這樣就可以實現對責任的分割,降低耦合性,明確了具體的職責和權力,有利于整個系統的優化。
3.缺點
當產品具有比較復雜的多層結構時,它的工廠類只有一個,這時候再以不變應萬變就成為它最大的缺點了。因為工廠類是整個組織的核心,它聚集了所有產品的創建邏輯,一旦工廠不能正常工作,整個系統都會受到影響,可擴展性較差。擴展性差一旦有新的需求,就不得不修改工廠邏輯,這樣就會導致工廠邏輯過為復雜,違背了開——閉原則。同時靜態工廠方法不利于形成基于繼承的等級結構。
二、工廠方法模式
1.理解
它是一個粒度很小的設計模式,因為模式的表現只是一個抽象的方法。工廠方法模式定義了一個用于創建對象的界面,讓子類決定具體實例化哪一個類。也就是在工廠和產品之間增加界面,工廠不再負責產品的實現,有借口針對不同條件返回不同的類實例,再由具體類實例去實現。工廠方法時簡單工廠的衍生,改進了許多簡單工廠的缺點,遵循了開——閉原則,實現了可擴展,可以用于更為復雜的產品結果場合。工廠方法可以理解為同樣是父親給兒子留了一筆錢,然后直接讓兒子去支配,怎么花父親一律不管。
2.優點
工廠方法模式客服了簡單工廠的很多缺點,它每個具體工廠只完成單一任務,而且遵循開——閉原則,代碼簡潔而且具有良好的擴展性。
3.缺點
如果有產品類需要修改,對應的工廠類也需要進行修改。一旦有多個產品類都需要修改的時候,對號入座的問題就出現了,這是對工廠類的修改就會變得相當復雜。因此工廠方法模式雖然有利于擴展但是不利于維護。
綜上所述,我們就可以知道針對不同的情況具體采用哪種模式對編程更有利了。當需要創建的對象比較少,客戶只知道傳入工廠的參數,并不關心如何創建對象的時候就可以采用簡單工廠模式;當類將創建對象的職責委托給多個幫助子類中的某一個時就可以采用工廠方法模式了。