我一直在阅读很多关于工厂模式方法的东西,并且在所有工厂中似乎都有一个基于switch-case的静态方法在运行时返回所需的产品,但这似乎违反了每当有新产品时,打开关闭原则需要修改工厂类别以进行必要的更改。
下面是一个代码,我认为也符合工厂模式,但我不确定这种方法是否正确。基本上我认为客户将知道它需要什么类型的工厂,基于它的情况下获得工厂独自处理的产品,
如果这是正确的方法,或者有更好的方法,请告诉我。
#include "iostream"
#include "memory"
using namespace std;
class AbstractDog{
public:
virtual void bark(void) = 0;
AbstractDog(){cout << "AbstractDog created"<<'\n';}
virtual ~AbstractDog(){cout << "AbstractDog destroyed"<<'\n';}
};
class chiwawa : public AbstractDog{
public:
void bark(void){
cout << "bark like chiwawa"<<'\n';
}
chiwawa(){cout << "chiwawa created"<<'\n';}
virtual ~chiwawa(){cout << "chiwawa destroyed"<<'\n';}
};
class alsatian : public AbstractDog{
public:
void bark(void){
cout << "bark like alsatian"<<'\n';
}
alsatian(){cout << "alsatian created"<<'\n';}
virtual ~alsatian(){cout << "alsatian destroyed"<<'\n';}
};
class AbstractDogFactory{
public:
virtual AbstractDog* getDog(void) = 0;
AbstractDogFactory(){cout << "AbstractDogFactory created"<<'\n';}
virtual ~AbstractDogFactory(){cout << "AbstractDogFactory destroyed"<<'\n';}
};
class smallDogFactory : public AbstractDogFactory{
public:
virtual AbstractDog* getDog(void){
return new chiwawa;
}
smallDogFactory(){cout << "smallDogFactory created"<<'\n';}
virtual ~smallDogFactory(){cout << "smallDogFactory destroyed"<<'\n';}
};
class bigDogFactory : public AbstractDogFactory{
public:
virtual AbstractDog* getDog(void){
return new alsatian;
}
bigDogFactory(){cout << "bigDogFactory created"<<'\n';}
virtual ~bigDogFactory(){cout << "bigDogFactory destroyed"<<'\n';}
};
int main() {
auto_ptr<AbstractDogFactory> m_ptr_fact(new bigDogFactory);
auto_ptr<AbstractDog> m_ptr_dog(m_ptr_fact->getDog());
m_ptr_dog->bark();
return 0;
}
答案 0 :(得分:0)
减少对工厂的代码更新的一种方法是使用带有函数指针的查找表(std::map
也足够了)。
代码将在表中搜索键,然后执行(deference)指向函数的指针,该函数返回指向已创建实例的指针。
添加新类型的狗时,您将更新数据表。但是,您需要编写一个函数来返回指向dog实例的指针;因此工厂被修改了。但是,(查找表的)基本搜索功能不需要改变。
编辑1:
一个例子:
typedef (Abstract_Dog *) (*Dog_Creator_Func_Pointer)();
struct Table_Entry
{
const char * dog_name;
Dog_Creator_Func_Pointer p_creator;
};
// Forward references
Abstract_Dog * Create_Greyhound();
Abstract_Dog * Create_Bulldog();
//...
static const Table_Entry creators[] =
{
{"greyhound", Create_Greyhound},
{"bulldog", Create_Bulldog},
//...
};
static const unsigned int creator_quantity =
sizeof(creators) / sizeof(creators[0]);
//...
for (unsigned int i = 0; i < creator_quantity; ++i)
{
if (dog_name == creators[i].dog_name)
{
return (*creators[i].p_creator)();
}
}
return nulptr;