標籤:方法 logs 利用 裝機 cto oid pat .cpp 之間
5. “對象建立”類模式
通過“對象建立”類模式繞開new,來避免對象建立(new)過程中所導致的緊耦合(依賴具體類),從而支援對象建立的穩定。它是介面抽象之後的第一步工作。
5.1 Factory 方法
動機:
在軟體系統中,經常面臨著建立對象的工作;由於需求的變化,需要建立的對象的具體類型經常變化。
如何應對這種變化?如何繞過常規的對象建立方法(new),提供一種“封裝機制”來避免客戶程式和這種“具體對象建立工作”的緊耦合?
程式碼範例:
仍然考慮檔案分割器案例,不考慮與建立對象無關的代碼部分,暫時忽略記憶體管理,專註於Factory 方法模式的應用。
在實現代碼1中,不同類型的檔案分割器類(File,Pic,Video等)繼承檔案分割器抽象基類。
在MainForm中,MainForm類依賴(編譯時間依賴)了具體的類BinarySpitter,違背了依賴倒置原則。此時即出現了動機中說明的建立對象過程中導致的緊耦合。
採用Factory 方法模式的解決方案見代碼2,考慮過程如下:
1.利用new方法建立的對象必須依賴於具體類,不可取;所以考慮建立一個類,利用其中方法的傳回值作為建立對象的結果;
2.然而單純的返回一個具體類的對象仍然沒有解決依賴倒置的問題,所以考慮將該類設計為一個抽象類別,具體的返回由其子類來確定。
3.依照上述思想建立工廠基類SplitterFactory(抽象類別),具體工廠(BinarySplitterFactory等)返回具體的對象。
4.MainForm使用過程中,聲明一個工廠欄位,在具體建立對象過程中採用統一的依賴於抽象的建立方法,即
ISplitter * splitter= factory->CreateSplitter(); //相當於多態new
而factory具體指向的物件類型由MainForm建構函式通過外界傳入。
註:可以從上述分析和代碼中看出,Factory 方法模式的使用,並不是為了消除變化(事實上變化不可能消除),而是將變化排除在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.cpp25 class MainForm : public Form26 {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.cpp19 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.cpp67 class MainForm : public Form68 {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(); //多態new82 83 splitter->split();84 85 }86 };
模式定義:
定義一個用於建立對象的介面,讓子類決定執行個體化哪一個類,Factory Method使得一個類的執行個體化延遲(目的:解耦 ,手段:虛函數)到子類。
類圖:
總結:
Factory Method模式用於隔離類對象的使用者與具體類型之間的耦合關係。面對一個經常變化的具體類型,緊耦合關係(new)會導致軟體的脆弱。
Factory Method模式通過物件導向的手法,將所有建立的具體對象延遲到子類,從而實現一種擴充(而非更改)的策略,較好地解決了這種緊耦合關係。
Factory Method模式解決“單個對象”的需求變化。缺點在於要求建立方法/參數相同。
c++ 設計模式8 (Factory Method Factory 方法)