C++實現設計模式: Factory 工廠模式

[譯]C++實現設計模式: Factory 工廠模式

 

 


Definition 

Basically a Factory consists of an interface class which is common to all of the implementation classes that the factory will create. Then you have the factory class which is usually a singleton class that spawns instances of these implementation classes.

譯文:

定義

一個典型的Factory 模式中一般包含一個接口類,所有的由工廠創造的實現類都繼承自這個接口類。工廠類一般採用單例模式實現,由工廠類對象實例產生具體的實現類。

Abstract Interface Class

So let us create a quick interface class to start with. In this example, I used IAnimal

譯文:

快讓我們來創建一個接口類來開始我們的工廠模式之旅吧。在這個例子中,我們使用 IAnimal 來定義表示抽象動物的接口類。

class IAnimal
{
public:
    virtual int GetNumberOfLegs() const = 0;
    virtual void Speak() = 0;
    virtual void Free() = 0;
}; 

Now for simplicity’s sake, I used a typedef to define a type for the function that is used by the implementation classes to create instances of IAnimal. This typedef is also used in declaring the map that maps the animal name to the function that creates that particular type of animal. You can use whatever calling convention you like, but for this example, I chose __stdcall.

譯文:

爲了代碼的簡潔,我使用typedef 來定義一個函數指針,用於方便在工廠類中創建繼承自IAnimal 類的子類對象實例。這個typedef 定義同樣用在根據動物名稱來影射創建具體動物對象的函數中。你可以根據你的使用習慣來定義它,但是我習慣上選擇__stdcall來聲明函數。

typedef IAnimal* (__stdcall *CreateAnimalFn)(void); 

Specific Implementation Class(es) 

Now come the implementation classes. These are the classes that implement the IAnimal interface. Here’re a few examples:

譯文:

接着我們來定義具體實現的動物子類。這些類都實現了IAnimal 接口類。下面我們來看看幾個例子:

// IAnimal implementations
class Cat : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << “Meow” << endl; }
    void Free() { delete this; }

    static IAnimal * __stdcall Create() { return new Cat(); }
};

class Dog : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << “Woof” << endl; }
    void Free() { delete this; }

    static IAnimal * __stdcall Create() { return new Dog(); }
};

class Spider : public IAnimal // Yeah it isn’t really an animal…
{
public:
    int GetNumberOfLegs() const { return 8; }
    void Speak() { cout << endl; }
    void Free() { delete this; }

    static IAnimal * __stdcall Create() { return new Spider(); }
};

class Horse : public IAnimal
{
public:
    int GetNumberOfLegs() const { return 4; }
    void Speak() { cout << “A horse is a horse, of course, of course.” << endl; }
    void Free() { delete this; }

    static IAnimal * __stdcall Create() { return new Horse(); }
};

Factory Class Declaration 

Now comes the Factory class. This is a singleton pattern implementation--meaning only one instance of the factory can ever be instantiated, no more, no less.

譯文:

下面我們來定義工廠類。我們採用單例模式來實現,這意味着能且只有一個工廠類實例被創建。

// Factory for creating instances of IAnimal
class AnimalFactory
{
private:
    AnimalFactory();
    AnimalFactory(const AnimalFactory &) { }
    AnimalFactory &operator=(const AnimalFactory &) { return *this; }

    typedef map FactoryMap;
    FactoryMap m_FactoryMap;
public:
    ~AnimalFactory() { m_FactoryMap.clear(); }

    static AnimalFactory *Get()
    {
        static AnimalFactory instance;
        return &instance;
    }

    void Register(const string &animalName, CreateAnimalFn pfnCreate);
    IAnimal *CreateAnimal(const string &animalName);
};

Factory Class Implementation

Now we need to work out a few definitions of the AnimalFactory class. Specifically the constructor, the Register, and the CreateAnimal functions.

譯文:

現在我們來看看工廠類AnimalFactory 的成員函數定義。這裏只分析默認構造函數,Register函數和 CreateAnimal 函數。

Constructor

The constructor is where you might consider registering your Factory functions. Though this doesn’t have to be done here, I’ve done it here for the purposes of this example. You could for instance register your Factory types with the Factory class from somewhere else in the code.

譯文:

構造函數

構造函數中需要註冊工廠類中的註冊工廠函數(可以生成的動物種類)。雖然這些函數不是在這裏完成,但是必須在工廠類的構造函數中註冊。當然你也可以工廠類的其他函數中註冊該工廠可以支持的類型對象實例化函數。

/* Animal factory constructor.
Register the types of animals here.
*/
AnimalFactory::AnimalFactory()
{
    Register(“Horse”, &Horse::Create);
    Register(“Cat”, &Cat::Create);
    Register(“Dog”, &Dog::Create);
    Register(“Spider”, &Spider::Create);
}

Type Registration

Now let us implement the Register function. This function is pretty straightforward since I used a std::map to hold the mapping between my string (the animal type) and the create function.

譯文:

類型註冊

現在我們來實現註冊成員函數。這個成員函數目標非常單一,我使用 std::map來影射動物類型名稱和創建這個類型動物所需要的create 函數指針。

void AnimalFactory::Register(const string &animalName, CreateAnimalFn pfnCreate)
{
    m_FactoryMap[animalName] = pfnCreate;
}

Type Creation

And last but not least, the CreateAnimal function. This function accepts a string parameter which corresponds to the string registered in the AnimalFactory constructor. When this function receives “Horse” for example, it will return an instance of the Horse class, which implements the IAnimal interface.

譯文:

類型創建

這裏最後介紹CreateAnimal 函數(其他函數這裏不做講解),這個函數接受的第一個參數:字符串類型,代表在AnimalFactory 構造函數中註冊了的可生成類型的名稱(動物名稱)。當這個函數收到參數“Horse”,工廠將要創建一個Horse類對象實例,這個類實現了IAnimal 接口。

IAnimal *AnimalFactory::CreateAnimal(const string &animalName)
{
    FactoryMap::iterator it = m_FactoryMap.find(animalName);
    if( it != m_FactoryMap.end() )
    return it->second();
    return NULL;
}

Example Usage Program

最後,我們來看看工廠類的使用例子吧。

int main( int argc, char **argv )
{
    IAnimal *pAnimal = NULL;
    string animalName;

    while( pAnimal == NULL )
    {
        cout << “Type the name of an animal or ‘q’ to quit: “;
        cin >> animalName;

        if( animalName == “q” )
        break;

        IAnimal *pAnimal = AnimalFactory::Get()->CreateAnimal(animalName);
        if( pAnimal )
        {
            cout << “Your animal has ” << pAnimal->GetNumberOfLegs() << ” legs.” << endl;
            cout << “Your animal says: “;
            pAnimal->Speak();
        }
        else
        {
            cout << “That animal doesn’t exist in the farm! Choose another!” << endl;
        }
        if( pAnimal )
            pAnimal->Free();
        pAnimal = NULL;
        animalName.clear();
    }
    return 0
原文地址:http://m.blog.csdn.net/blog/johnnyelf83/8881439
發佈了18 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章