本来打算原创的,但是读到的这篇文章非常好的诠释了我比较常用的工厂模式,因此这一回翻译一篇来自Cale Dunlap的一篇文章,这里先谢谢Cale。
原文链接:
http://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus
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 模式中一般包含一个接口类,所有的由工厂创造的实现类都继承自这个接口类。工厂类一般采用单例模式实现,由工厂类对象实例产生具体的实现类。
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);
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(); } };
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); };
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
函数。
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); }
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; }
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; }
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; }
注释:
本来打算每周写一篇设计模式的文章的,五一放假期间偷懒没有写,以后要多多坚持。考虑到模式识别文章讲清楚比较难,以后两周写一次模式识别的文章吧。