工厂模式
工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。
核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
类图
稳定点
// 抽象产品
class ConfAbstract {
public:
virtual void getConf()=0;
};
// 抽象工厂类
class ConfAbstractFactory{
public:
virtual ConfAbstract* createConfObj() = 0;
};
变化点
// 具体产品: etcdConf
class etcdConf : public ConfAbstract {
public:
virtual void getConf() {
cout << "从etcd中加载配置文件" << endl;
}
};
// 生产etcd配置的工厂类
class etcdConfFactory : public ConfAbstractFactory {
public:
virtual ConfAbstract *createConfObj() {
return new etcdConf;
}
};
如果需要新增产品,新增代码
// 具体产品: fileConf
class fileConf : public ConfAbstract {
public:
virtual void getConf() {
cout << "从本地文件中加载配置文件" << endl;
}
};
// 生产file配置的工厂类
class fileConfFactory : public ConfAbstractFactory {
public:
virtual ConfAbstract *createConfObj() {
return new fileConf;
}
};
调用
在解析配置的函数parseConf
中,发生了多态:传入的是ConfAbstract
的子类,调用的是实现了重写的方法getConf()
// parseConf解析配值的函数
void parseConf(ConfAbstract *pConf) {
// 加载配置
pConf->getConf();
// 解析配置
// 释放内存
if (nullptr != pConf) {
delete pConf;
pConf = nullptr;
}
}
整个实例中,变化点是生产具体的工厂类pFac = new etcdConfFactory;
调用etcd
的加载函数getConf()
// 1. 申请工厂类
ConfAbstractFactory *pFac = nullptr;
// 2. 申请具体工厂
ConfAbstract *pConf = nullptr;
// 3. 产生具体工厂类
pFac = new etcdConfFactory; // 变化点
// 4. 通过具体工厂生产具体产品
pConf = pFac->createConfObj(); // etcdConfFactory::createConfObj() 返回的是etcdConf的类
// 5. 调用具体产品的对象的功能,并释放内存
parseConf(pConf);
// 6.释放抽象工厂类
if (nullptr != pFac) {
delete pFac;
pFac = nullptr;
}
调用file
的加载函数getConf()
// 1. 申请工厂类
ConfAbstractFactory *pFac = nullptr;
// 2. 申请具体工厂
ConfAbstract *pConf = nullptr;
// 3. 产生具体工厂类
pFac = new fileConfFactory; // 变化点
// 4. 通过具体工厂生产具体产品
pConf = pFac->createConfObj(); // etcdConfFactory::createConfObj() 返回的是etcdConf的类
// 5. 调用具体产品的对象的功能,并释放内存
parseConf(pConf);
// 6.释放抽象工厂类
if (nullptr != pFac) {
delete pFac;
pFac = nullptr;
}
如果写成一个函数,那么生产工厂的过程违背了开闭原则
void func(char *factoryName){
// 1. 申请工厂类
ConfAbstractFactory *pFac = nullptr;
// 2. 申请具体工厂
ConfAbstract *pConf = nullptr;
// 3. 产生具体工厂类
if (strcmp(factoryName, "etcd") == 0) {
pFac = new etcdConfFactory;
} else if (strcmp(factoryName, "file") == 0) {
pFac = new fileConfFactory;
} else {
printf("记录日志,或者接抛出错误\n");
return ;
}
// 4. 通过具体工厂生产具体产品
pConf = pFac->createConfObj(); // etcdConfFactory::createConfObj() 返回的是etcdConf的类
// 5. 调用具体产品的对象的功能,并释放内存
parseConf(pConf);
// 6.释放抽象工厂类
if (nullptr != pFac) {
delete pFac;
pFac = nullptr;
}
}