在C++工厂模式中,如果需求变更,或增加新的需求,那么一般需要修改工厂类中的对外接口中的选择语句。
例如:
Father * Create(string name)
{
if ("Son1" == name)
return new Son1();
else if ("Son2" == name)
return new Son2();
//.......
//每次有新的子类时,需要更改这里
//还要Include相应的头文件,甚至还有更多的地方要改
}
这违反了“开闭”原则。
以下是C++中的解决方法之一:
//需求:
//1. 通过工厂类,传入类名,返回该类的对象指针
//2. 添加新的子类时,不需要更改现有任何代码
//工厂类,供外部调用
class Factory
{
public:
//外部调用接口,根据不同的类名创建对应的类对象指针
Father * Create(std::string name)
{
return Father::Create(name);
}
};
//Father类
//收集子类名称及对应子类的一个对象指针
class Father
{
class Element
{
public:
Father * m_pf;
std::string m_name;//存储子类名
};
//存储子类的名称及其对象指针一个
static std::list<Element> m_lstObj;
public:
//外部调用接口,用于创建子类对象
//当有新的子类时,就不必修改此函数了
static Father * Create(std::string name)
{
std::list<Element>::iterator it = m_lstObj.begin();
for(; it != m_lstObj.end(); ++it)
{
if(it->m_name == name)
{
return it->m_pf->NewSon();
}
}
return NULL;
};
protected:
//子类必须实现接口,用于实现创建子类对象
virtual Father * NewSon() = 0;
void AddElment(Father * pf, std::string name)
{
Element e;
e.m_pf = pf;
e.m_name = name;
m_lstObj.push_back(e);
};
};
//静态成员初始化
std::list<Father::Element> Father::m_lstObj;
//子类
class Son1:public Father
{
protected:
virtual Father * NewSon()
{
return new Son1();
};
private:
//在初始化m_bFlag时,向父类提交类名及一个对象指针
static bool Register()
{
Son1 * ps = new Son1();
ps->AddElment(ps,"Son1");
return true;
};
//标记子类是否注册,static变量会在Main函数调用前执行初始化
static bool m_bFlag;
};
//借助静态成员变量初始化,进行注册
bool Son1::m_bFlag = Son1::Register();