<!--完整代码下载链接:点击下载完整代码示例-->
1.描述
在项目开发中经常会遇到根据不同的条件创建不同的对象,然后对该对象进行操作,一般都包括许多的switch -case分支如下:
CBase* pBase(NULL);
switch (type_variable)
{
case obj1: pBase = new CBaseDerivate1();break;
case obj2: pBase = new CBaseDerivate2();break;
...
case objN: pBase = new CBaseDerivateN();break;
}
或者形如下面的情况:
CBase* pBase(NULL);
if (!strcmp(string_for_type, "Type1")) pBase = new CBaseDerivate1();
else if (!strcmp(string_for_type, "Type2")) pBase = new CBaseDerivate2();
...
else if (!strcmp(string_for_type, "TypeN")) pBase = new CBaseDerivateN();
上面两中创建对象的方法使用起来很繁琐,并且当对象的数量增加时,维护起来很麻烦,下面介绍简单工厂模式来解决该问,采用两种方法实现,一种是采用注册函数指针,另外一种采用模板参数。
2.两种方法实现简单工厂模式
例子:假设有一个动物类,需要根据不同的条件创建不同的动物
方法一:采用注册函数指针的方式
1.定义抽象动物类
class IAnimal
{
public:
virtual int GetNumberOfLegs() const = 0;
virtual void Speak() = 0;
virtual void Free() = 0;
};
2.定义具体的动物实例
// 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(); }
};
3.定义工厂
定义创建对象函数指针:
typedef IAnimal* (__stdcall *CreateAnimalFn)(void);
// 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);
};
构造函数进行具体创建函数的注册
/* 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);
}
void AnimalFactory::Register(const string &animalName, CreateAnimalFn pfnCreate)
{
m_FactoryMap[animalName] = pfnCreate;
}
创建实例接口:
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;
}
方法二:采用模板参数的方式
方法一需要每个子类都写一个创建实例的函数create,存在大量重复,同时,各个实例需要继承同一个父类,同时该方法比较容易理解。
下面采用模板参数的方法。
1.首先定义如下两个模板类
template <class BT>
class FactoryPlant
{
public:
FactoryPlant() {}
virtual ~FactoryPlant() {}
virtual BT *createInstance() = 0;
};
template <class BT,class ST>
class Factory : public FactoryPlant<BT>
{
public:
Factory() {}
virtual ~Factory() {}
virtual BT *createInstance() {return new ST;}
};
FactoryPlant为实际工厂类,Factory类有两个参数,一个是抽象基类BT,另一个是待实例化的类ST。
FactoryPlant 包含创建实例的纯虚函数createInstance,子类Factory实现该方法。
2.创建具体子类
//抽象动物接口
class IAnimal
{
public:
virtual int GetNumberOfLegs() const = 0;
virtual void Speak() = 0;
virtual void Free() = 0;
typedef FactoryPlant<IAnimal> SimpleBaseClassFactory;
};
class Cat : public IAnimal
{
public:
int GetNumberOfLegs() const { return 4; }
void Speak() { cout << "Meow" << endl; }
void Free() { delete this; }
static Factory<IAnimal,Cat> myFactory;
};
Factory<IAnimal,Cat> Cat::myFactory;
class Dog : public IAnimal
{
public:
int GetNumberOfLegs() const { return 4; }
void Speak() { cout << "Woof" << endl; }
void Free() { delete this; }
static Factory<IAnimal,Dog> myFactory;
};
Factory<IAnimal,Dog> Dog::myFactory;
class Spider : public IAnimal //
{
public:
int GetNumberOfLegs() const { return 8; }
void Speak() { }
void Free() { delete this; }
static Factory<IAnimal,Spider> myFactory;
};
Factory<IAnimal,Spider> Spider::myFactory;
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 Factory<IAnimal,Horse> myFactory;
};
Factory<IAnimal,Horse> Horse::myFactory;
上面不是采用函数指针,而是每个子类采用一个静态的factory实例,由于是静态的成员,需要在类外面进行定义,否则编译将会出现
unresolved externals的错误。
3.创建函数
IAnimal *CreateAnimal(std::map<string,IAnimal::SimpleBaseClassFactory *> &factories,const string &animalName)
{
return factories[animalName]->createInstance();
}
4.客户端使用
void main()
{
IAnimal *pAnimal = NULL;
//Register
std::map<string,IAnimal::SimpleBaseClassFactory *> factories;
factories["Cat"] = &Cat::myFactory;
factories["Dog"] = &Dog::myFactory;
factories["Spider"] = &Spider::myFactory;
factories["Horse"] = &Horse::myFactory;
string animalName;
while( pAnimal == NULL )
{
cout << "Type the name of an animal or 'q' to quit: ";
cin >> animalName;
if( animalName == "q" )
break;
IAnimal *pAnimal = CreateAnimal(factories,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();
}
上面的map的创建是在主函数中,在比较复杂的场景中,可以在一个单例中创建该map,如果需要添加实例化其他的类,只需要将该类的factory添加到map中即可。