設計模式學習之Factory 方法模式和原型模式

來源:互聯網
上載者:User

提出問題-分析問題-解決問題,這是一般寫議論文的常規思路,正是通常文章採用這種方法來寫的,所以學習一種理論,也是順著這個思想來的,學習設計模式也不例外。在學任何一種模式前,一定要首先搞清楚這種模式產生的背景,即實際編碼或修改維護代碼中遇到的問題,然後分析出現的問題,是否違背了設計模式的原則或物件導向的思想,然後在引出解決這個問題用到的設計模式,最後對比總結,歸納出此種模式適用的場合及優缺點。

1.Factory 方法模式
定義:定義一個用於建立對象的介面,讓子類決定執行個體化哪一個類,Factory 方法使一個類的執行個體化延遲到其子類

簡單原廠模式VSFactory 方法模式:簡單原廠模式的最大優點在於工廠類中包含了必要的邏輯判斷,根據用戶端的選擇條件動態執行個體化相關的類,對於用戶端來說,去除了與具體產品的依賴。前面的簡單原廠模式的計算機例子中,只需要把‘+’給工廠,工廠自動給出了相應的執行個體,用戶端只要去做運算就可以了,不同的執行個體會實現不同的運算。但問題是,如果要增加一個功能,需要在工廠類的方法裡加‘case’分支條件,這樣不但對擴充開放了,對修改也開放了,違背了開放-封閉原則。既然這個工廠類與分支耦合,那麼就對它下手,根據依賴倒轉原則,把工廠類抽象出一個介面,這個介面只有一個方法,就是建立抽象產品的Factory 方法,然後所有的生產具體類的工廠長就去實現這個介面,這樣轉成Factory 方法模式後就不需要更改原有的工廠類了,只需要增加此功能的運算類和相應的工廠類就可以了,這樣只有擴充的變化,沒有修改的變化,就符合了開放-封有閉原則。

Factory 方法模式實現時,用戶端需要決定執行個體化哪一個工廠來實現運算類,選擇判斷的問題還是存在的,只是把簡單工廠的內部邏輯判斷移到了用戶端來進行,想要加功能,本來是改工廠類的,而現在是修改用戶端。

執行個體:

#include <string>#include <iostream>using namespace std;//執行個體基類class LeiFeng{public:virtual void Sweep(){cout<<"雷鋒掃地"<<endl;}};//學雷鋒的大學生,相當於 ConcreteProductclass Student: public LeiFeng{public:virtual void Sweep(){cout<<"大學生掃地"<<endl;}};//學雷鋒的志願者,相當於 ConcreteProductclass Volenter: public LeiFeng{public :virtual void Sweep(){cout<<"志願者掃地"<<endl;}};//工場基類 Creatorclass LeiFengFactory{public:virtual LeiFeng* CreateLeiFeng(){return new LeiFeng();}};//工場具體類class StudentFactory : public LeiFengFactory{public :virtual LeiFeng* CreateLeiFeng(){return new Student();}};class VolenterFactory : public LeiFengFactory{public:virtual LeiFeng* CreateLeiFeng(){return new Volenter();}};//用戶端int main(){LeiFengFactory *sf=new LeiFengFactory();LeiFeng *s=sf->CreateLeiFeng();s->Sweep();delete s;delete sf;return 0;}

優點:Factory 方法模式是簡單原廠模式的進一步抽象和推廣,由於使用了多態性,Factory 方法模式保持了簡單原廠模式封裝對象建立過程的優點,而且遵循開放-封閉原則。Factory 方法模式的缺點是由於每加一個產品,就需要加一個產品工廠的類,增加了額外的開發量。

2.原型模式
定義:從一個對象再建立另外一個可定製的對象,而無需知道任何建立的細節,並能提高建立的效能,說白了就是將一個對象完整地copy一份

執行個體:

#include <iostream>#include <vector>#include <string>using namespace std;class Prototype //抽象基類{private:string m_strName;public:Prototype(string strName){ m_strName = strName; }Prototype() { m_strName = " ";}void Show(){cout<<m_strName<<endl;}virtual Prototype* Clone() = 0;};// class ConcretePrototype1class ConcretePrototype1 : public Prototype{public:ConcretePrototype1(string strName) : Prototype(strName){}ConcretePrototype1(){}virtual Prototype* Clone(){ConcretePrototype1 *p = new ConcretePrototype1();*p = *this; //複製對象return p;}};// class ConcretePrototype2class ConcretePrototype2 : public Prototype{public:ConcretePrototype2(string strName) : Prototype(strName){}ConcretePrototype2(){}virtual Prototype* Clone(){ConcretePrototype2 *p = new ConcretePrototype2();*p = *this; //複製對象return p;}};//用戶端int main(){ConcretePrototype1* test = new ConcretePrototype1("小王");ConcretePrototype2* test2 = (ConcretePrototype2*)test->Clone();test->Show();test2->Show();return 0;}

應用場合:如果要對一個對象重複建立,那麼每new一次,都需要執行一次建構函式,如果建構函式的執行時間很長,那麼多次執行這個初始化就實在是太低效了。一般在初始化的資訊不發生變化的情況下,複製是最好的方法,這既隱藏了對象建立的細節,又對效能是大大的提高,不用重新初始化對象,而是動態地獲得對象運行時的狀態。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.