工厂模式
经常听人说工厂方法+反射机制+单例模式,可以解决大多数的对象创建的问题。但是什么是工厂方法呢?还有其他什么鬼呢?
这里先介绍简单的工厂方法,也就是Factory Method方法,既然这是简单的,那岂不是还有复制的或者其它,那是当然的。不过都得一步一步来嘛。
做什么?
首先明确我们用工厂模式做什么?
那么我们的客户来需求了,”我们要创建在一个模块中创建A类的对象“,
”没关系,我知道那个代码在哪里,我们就在那里创建A的对象。
// file1
class A {
// ....
}; // class A
// ...
A* a = new A();
// ...
现在突然客户背后站了会说,“这个不太好,我们可能后面需要创建Class B, C , D ...”。
默默的说一句,md,你怎么这么多问题啊(小声)。 “没问题,我们改代码,那么我们将对象指针抽象一下,提一个基类吧,抽象一下,好吧。”
// commom file
{
class Base {
// ....
}; // class Base
}
// file1
{
class A : public Base{
// ....
}; // class A
}
// file2
{
class B : public Base{
// ....
}; // class B
}
// ...
Base* base = new A(); // Base* base = new B();
// ...
这时候客户说,”好像哈,我觉得..., 是这样的,我觉得 你左边那部分好像有点那个意思了,但是你这右边还是有点不行啊,你用new创建,那不是和具体的创建绑定死了,
这不行你还得改。对了,五点我该下班了,你也早点下班“。
"md(低声), ok,没得问题"。
那么怎么办呢,感觉可能拨了键盘上的头发,这样吧,我们通过其他的类来返回这个对象指针吧。
既然是其他类返回的这个对象指针,那么我们就叫那个类为工厂类吧。
class BaseFactory {
public:
Base* CreateNewBase {
return new A(); // return new B();
}
}
"完蛋,明天又要开例会了", 自己心中暗中一想,完蛋虽然上面这样写,好像是没有用new创建,但是不是还是换汤不换药嘛,还得改。
”咦,不是还有多态嘛“,对啊多态,这时候virtual一下子跳入了脑海。
class BaseFactory {
public:
virtual Base* CreateNewBase = 0;
}
class FactoryA : public BaseFactory {
public:
virtual Base* CreateNewBase override;
}
class FactoryB : public BaseFactory {
public:
virtual Base* CreateNewBase override;
}
例会上,屁颠屁颠的和客户讲了下这个,感觉很自豪。
客户摸了摸自己浓密的头发,说到”不错,我就是想让你做成类似这个样,但是我当时没想起名字, 不错了,但是这里有个问题 。。。“
”啥,还有问题“。
”就是哈,我能不能通过注册的方式,申请一个类的对象啊,比如我只会配置json文件,我也看不懂代码, 而且我想通过一张表来保存我想创建的对象,随时随地创建可以吗“。
”。。。。。。,我觉得这个得加钱(小声)。我觉得可能行吧,但是我有点不舒服,今天感觉有点感冒,我要去医院检查“。
”啥,新冠?那你先去体检吧“。
我们来描述下上面那个场景的代码结构
故事中的A,B就是ConcreteProduct, Base就是Product, BaseFactory就是Creator, FactoryA就是ConcreteCreator
那么我们用代码重现structure
#include <iostream>
namespace DesignPatterns {
class Product {
// ...
};
class ConcreteProductA : public Product {
public:
ConcreteProductA() {
std::cout << "A Created" << std::endl;
}
// ...
};
class ConcreteProductB : public Product {
public:
ConcreteProductB() {
std::cout << "B Created" << std::endl;
}
//
};
class Creator {
public:
virtual Product* CreateProduct() = 0;
};
class ConcreteCreatorA : public Creator {
public:
virtual Product* CreateProduct() override {
return new ConcreteProductA();
}
};
class ConcreteCreatorB : public Creator {
public:
virtual Product* CreateProduct() override {
return new ConcreteProductB();
}
};
class FactoryTest {
private:
Creator* creator = nullptr;
Product* product = nullptr;
public:
FactoryTest(Creator* crt) : creator(crt){}
FactoryTest() = delete;
bool Init() {
if (creator) {
this->product = creator->CreateProduct();
}
}
};
} // namespace DesignPatterns
int main(int argc, char* argv[]) {
using namespace DesignPatterns;
Creator* crt = new ConcreteCreatorA();
FactoryTest bar(crt);
bar.Init();
return 0;
}
运行结果
要点总结
- Factory Method模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。
- Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种拓展而非修改的策略,较好的解决了这种紧耦合关系。
- Factory Method 模式解决了“单个对象”的需求变化,缺点在于要求创建方法与参数相同。