1. 程式人生 > >c++ 設計模式8 (Factory Method 工廠方法)

c++ 設計模式8 (Factory Method 工廠方法)

更改 itl logs 客戶 eos image 分享 一個 工廠方法模式

5. “對象創建”類模式

通過“對象創建”類模式繞開new,來避免對象創建(new)過程中所導致的緊耦合(依賴具體類),從而支持對象創建的穩定。它是接口抽象之後的第一步工作。

5.1 工廠方法

動機:

在軟件系統中,經常面臨著創建對象的工作;由於需求的變化,需要創建的對象的具體類型經常變化。

如何應對這種變化?如何繞過常規的對象創建方法(new),提供一種“封裝機制”來避免客戶程序和這種“具體對象創建工作”的緊耦合?

代碼示例:

仍然考慮文件分割器案例,不考慮與創建對象無關的代碼部分,暫時忽略內存管理,專註於工廠方法模式的應用。

在實現代碼1中,不同類型的文件分割器類(File,Pic,Video等)繼承文件分割器抽象基類。

在MainForm中,MainForm類依賴(編譯時依賴)了具體的類BinarySpitter,違背了依賴倒置原則。此時即出現了動機中說明的創建對象過程中導致的緊耦合。

采用工廠方法模式的解決方案見代碼2,考慮過程如下:

1.利用new方法創建的對象必須依賴於具體類,不可取;所以考慮創建一個類,利用其中方法的返回值作為創建對象的結果;

2.然而單純的返回一個具體類的對象仍然沒有解決依賴倒置的問題,所以考慮將該類設計為一個抽象類,具體的返回由其子類來確定。

3.依照上述思想創建工廠基類SplitterFactory(抽象類),具體工廠(BinarySplitterFactory等)返回具體的對象。

4.MainForm使用過程中,聲明一個工廠字段,在具體創建對象過程中采用統一的依賴於抽象的創建方法,即

ISplitter * splitter= factory->CreateSplitter(); //相當於多態new

而factory具體指向的對象類型由MainForm構造函數通過外界傳入。

註:可以從上述分析和代碼中看出,工廠方法模式的使用,並不是為了消除變化(事實上變化不可能消除),而是將變化排除在MainForm之外(類比將變化趕到一個小範圍),使其更加可控,從而使文件分割器的設計和使用滿足面向對象設計原則,在應對變化時表現出優勢。

技術分享
 1 //FileSpiltter1.cpp
 2 class ISplitter{
 3 public:
 4     virtual void split()=0;
 5     virtual ~ISplitter(){}
 6 };
 7 
 8 class BinarySplitter : public ISplitter{
 9     
10 };
11 
12 class TxtSplitter: public ISplitter{
13     
14 };
15 
16 class PictureSplitter: public ISplitter{
17     
18 };
19 
20 class VideoSplitter: public ISplitter{
21     
22 };
23 
24 //MaiForm1.cpp
25 class MainForm : public Form
26 {
27     TextBox* txtFilePath;
28     TextBox* txtFileNumber;
29     ProgressBar* progressBar;
30 
31 public:
32     void Button1_Click(){
33 
34 
35         
36         ISplitter * splitter=
37             new BinarySplitter();//依賴具體類
38         
39         splitter->split();
40 
41     }
42 };
技術分享

技術分享
 1 //ISpiltterFactory.cpp
 2 
 3 //抽象類
 4 class ISplitter{
 5 public:
 6     virtual void split()=0;
 7     virtual ~ISplitter(){}
 8 };
 9 
10 
11 //工廠基類
12 class SplitterFactory{
13 public:
14     virtual ISplitter* CreateSplitter()=0;
15     virtual ~SplitterFactory(){}
16 };
17 
18 //FileSpiltter2.cpp
19 
20 //具體類
21 class BinarySplitter : public ISplitter{
22     
23 };
24 
25 class TxtSplitter: public ISplitter{
26     
27 };
28 
29 class PictureSplitter: public ISplitter{
30     
31 };
32 
33 class VideoSplitter: public ISplitter{
34     
35 };
36 
37 //具體工廠
38 class BinarySplitterFactory: public SplitterFactory{
39 public:
40     virtual ISplitter* CreateSplitter(){
41         return new BinarySplitter();
42     }
43 };
44 
45 class TxtSplitterFactory: public SplitterFactory{
46 public:
47     virtual ISplitter* CreateSplitter(){
48         return new TxtSplitter();
49     }
50 };
51 
52 class PictureSplitterFactory: public SplitterFactory{
53 public:
54     virtual ISplitter* CreateSplitter(){
55         return new PictureSplitter();
56     }
57 };
58 
59 class VideoSplitterFactory: public SplitterFactory{
60 public:
61     virtual ISplitter* CreateSplitter(){
62         return new VideoSplitter();
63     }
64 };
65 
66 //MainForm2.cpp
67 class MainForm : public Form
68 {
69     SplitterFactory*  factory;//工廠
70 
71 public:
72     
73     MainForm(SplitterFactory*  factory){
74         this->factory=factory;
75     }
76     
77     void Button1_Click(){
78 
79         
80         ISplitter * splitter=
81             factory->CreateSplitter(); //多態new
82         
83         splitter->split();
84 
85     }
86 };
技術分享

模式定義:

定義一個用於創建對象的接口,讓子類決定實例化哪一個類,Factory Method使得一個類的實例化延遲(目的:解耦 ,手段:虛函數)到子類。

類圖:

技術分享

總結:

Factory Method模式用於隔離類對象的使用者與具體類型之間的耦合關系。面對一個經常變化的具體類型,緊耦合關系(new)會導致軟件的脆弱。

Factory Method模式通過面向對象的手法,將所有創建的具體對象延遲到子類,從而實現一種擴展(而非更改)的策略,較好地解決了這種緊耦合關系。

Factory Method模式解決“單個對象”的需求變化。缺點在於要求創建方法/參數相同。

c++ 設計模式8 (Factory Method 工廠方法)