設計模式之簡單工廠,工廠方法模式(c++)


問題描述


在面向對象系統設計中經常可以遇到以下的兩類問題:

1)為瞭提高內聚(Cohesion)和松耦合(Coupling),我們經常會抽象出一些類的公共接口以形成抽象基類或者接口。這樣我們可以通過聲明一個指向基類的指針來指向實際的子類實現, 達到瞭多態的目的。


這裡很容易出現的一個問題 n 多的子類繼承自抽象基類, 我們不得不在每次要用到子類的地方就編寫諸如 new ×××;的代碼。這裡帶來兩個問題:


->1.客戶程序員必須知道實際子類的名稱(當系統復雜後, 命名將是一個很不好處理的問題, 為瞭處理可能的名字沖突, 有的命名可能並不是具有很好的可讀性和可記憶性, 就姑且不論不同程序員千奇百怪的個人偏好瞭。)


->2.程序的擴展性和維護變得越來越困難。


2)還有一種情況就是在父類中並不知道具體要實例化哪一個具體的子類。


假設我們在類 A 中要使用到類 B, B 是一個抽象父類,在 A 中並不知道具體要實例化那一個 B 的子類,但是在類A的子類D中是可以知道的。在A中我們沒有辦法直接使用類似於new×××的語句,因為根本就不知道×××是什麼。


以上兩個問題也就引出瞭 Factory 模式的兩個最重要的功能:

1)定義創建對象的接口,封裝瞭對象的創建;

2)使得具體化類的工作延遲到瞭子類中。


在第一個問題中,我們經常就是聲明一個創建對象的接口,並封裝瞭對象的創建過程。 Factory 這裡類似於一個真正意義上的工廠(生產對象)。


在第二個問題中,我們需要提供一個對象創建對象的接口,並在子類中提供其具體實現(因為隻有在子類中可以決定到底實例化哪一個)。


UML類圖


對於工廠模式,具體上可以分為三類:



  1. 簡單工廠模式;

  2. 工廠方法模式;

  3. 抽象工廠模式。


對於上面的三種工廠模式,從上到下逐步抽象,並且更具一般性。本篇主要論述第一類(簡單工廠模式)和第二類(工廠方法模式)。


第一種情況下(對應的就是“簡單工廠模式”):



上圖所示的Factory模式經常在系統開發中用到,但是這並不是 Factory模式的最大威力所在(因為這可以通過其他方式解決這個問題)。Factory模式不單是提供瞭創建對象的接口,其最重要的是延遲瞭子類的實例化(第二個問題)。


如下圖所示(對應的就是工廠方法模式):



這種模式的應用並不是隻是為瞭封裝對象的創建,而是要把對象的創建放到子類中實現: Factory 中隻是提供瞭對象創建的接口,其實現將放在 Factory 的子類ConcreteFactory 中進行。


適用場合


簡單工廠模式:



  1. 在程序中,需要創建的對象很多,導致對象的new操作多且雜時,需要使用簡單工廠模式;

  2. 由於對象的創建過程是我們不需要去關心的,而我們註重的是對象的實際操作,所以,我們需要分離對象的創建和操作兩部分,如此,方便後期的程序擴展和維護。



工廠方法模式:


工廠方法模式的意義是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類當中。它修正瞭簡單工廠模式中不遵守開放—封閉原則。核心工廠類不再負責產品的創建,這樣核心類成為一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可以使系統在不修改具體工廠角色的情況下引進新的產品。



  1. 在設計的初期,就考慮到產品在後期會進行擴展的情況下,可以使用工廠方法模式;

  2. 產品結構較復雜的情況下,可以使用工廠方法模式;



由於使用設計模式是在詳細設計時,就需要進行定奪的,所以,需要權衡多方面的因素,而不能為瞭使用設計模式而使用設計模式。


代碼實現


簡單工廠模式:














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


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


73


74


75


76


77


78


79


80


81


#include

<iostream>


#include

<string>


using namespace std;


//基類


class Operation


{


public:


    double numberA,

numberB;


    virtual double  getResult()


    {


        return 0;


    }


};


//加法


class addOperation

:
public Operation


{


    double getResult()


    {


        return numberA

+ numberB;


    }


};



//減法


class subOperation

:
public Operation


{


    double getResult()


    {


        return numberA

- numberB;


    }


};


//乘法


class mulOperation

:
public Operation


{


    double getResult()


    {


        return numberA*numberB;


    }


};


//除法


class divOperation

:
public Operation


{


    double getResult()


    {


        return numberA

/ numberB;


    }


};


//工廠類


class operFactory


{


public:


    static Operation

*createOperation(
char c)


    {<br>//在c#中可以用反射來取消判斷時用的switch,那麼c++中用的是啥呢?RTTI?


        switch (c)


        {


        case '+':


            return new addOperation;


            break;



        case '-':


            return new subOperation;


            break;



        case '*':


            return new mulOperation;


            break;



        case '/':


            return new divOperation;


            break;


        }


    }


};



int main()


{


    Operation

*oper = operFactory::createOperation(
'+');


    oper->numberA

= 9;


    oper->numberB

= 99;


    cout

<< oper->getResult() << endl;


    return 0;


}



運行結果:




工廠方法模式:












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


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


73


74


75


76


77


78


79


80


81


82


83


84


85


86


87


88


89


90


91


92


93


94


95


96


97


98


#include

<iostream>


#include

<string>


using namespace std;



class Operation


{


public:


    double numberA,

numberB;


    virtual double  getResult()


    {


        return 0;


    }


};



class addOperation

:
public Operation


{


    double getResult()


    {


        return numberA

+ numberB;


    }


};




class subOperation

:
public Operation


{


    double getResult()


    {


        return numberA

- numberB;


    }


};



class mulOperation

:
public Operation


{


    double getResult()


    {


        return numberA*numberB;


    }


};



class divOperation

:
public Operation


{


    double getResult()


    {


        return numberA

/ numberB;


    }


};



class IFactory


{


public:


    virtual Operation

*createOperation() = 0;


};



class AddFactory

:
public IFactory


{


public:


    static Operation

*createOperation()


    {


        return new addOperation();


    }


};




class SubFactory

:
public IFactory


{


public:


    static Operation

*createOperation()


    {


        return new subOperation();


    }


};



class MulFactory

:
public IFactory


{


public:


    static Operation

*createOperation()


    {


        return new mulOperation();


    }


};



class DivFactory

:
public IFactory


{


public:


    static Operation

*createOperation()


    {


        return new divOperation();


    }


};



int main()


{


    Operation

*oper = MulFactory::createOperation();


    oper->numberA

= 9;


    oper->numberB

= 99;


    cout

<< oper->getResult() << endl;


    return 0;


}



運行結果:



---------------------------------------------------------













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


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


#include

<iostream>


#include

<string>


using namespace std;


//實例基類,相當於Product(為瞭方便,沒用抽象)


class LeiFeng


{


public:


    virtual void sweep()


    {


        cout

<< 
"雷鋒掃地" <<

endl;


    }



    void wash()


    {


        cout

<< 
"雷鋒洗衣服" <<

endl;


    }


};


//學雷鋒的大學生,相當於ConcreteProduct


class Student

:
public LeiFeng


{


public:


    virtual void sweep(){


        cout

<< 
"大學生掃地" <<

endl;


    }


};


//學雷鋒的志願者,相當於ConcreteProduct


class Volunteer

:
public LeiFeng


{


public:


    virtual void sweep(){


        cout

<< 
"zhiyaunzhe" <<

endl;


    }


};



//工廠基類Creator


class LeiFengFactory


{


public:


    virtual LeiFeng

*createLeiFeng()


    {


        return new LeiFeng();


    }


};



//工廠具體類


class StudentFactory

:
public LeiFengFactory


{


public:


    virtual LeiFeng

*createLeiFeng()


    {


        return new Student();


    }


};



class VolFactory

:
public LeiFengFactory


{


public:


    virtual LeiFeng

*createLeiFeng()


    {


        return new Volunteer();


    }


};



int main()


{


    LeiFengFactory

*sf = 
new LeiFengFactory();


    LeiFeng

*s = sf->createLeiFeng();


    s->sweep();


    delete s;


    delete sf;


    return 0;


}



運行結果:




  



參考文獻:  


《大話設計模式 C++》


《C++設計模式》

0 個評論

要回覆文章請先登錄註冊