1)定义创建对象的接口,封装了对象的创建;
2)使得具体化类的工作延迟到了子类中。
在第一个问题中,我们经常就是声明一个创建对象的接口,并封装了对象的创建过程。Factory这里类似于一个真正意义上的工厂(生产对象)。在第二个问题中,我们需要提供一个对象创建对象的接口,并在子类中提供其具体实现(因为只有在子类中可以决定到底实例化哪一个类)。
第一种情况的Factory的结构示意图为:
这种简单工厂模式是我自己在项目开发中用的比较多的,比如视频嗅探包含11个视频网站,所以我定义视频解析基类,11个网站分别派生,共享同一个解析接口,
然后factory根据site type觉得生成那种类型的对象。大致代码流程如下:
factory* pf = new factory();
productBase* product = pf->createProduct(type);
product->parseinterface();
其中switch、if-else只集中在factory类中的createProduct中,大大减轻了维护和扩展成本。
第二种情况:Factory模式不单是提供了创建对象的接口,其最重要的是延迟了子类的实例化,以下是这种情况的一个Factory的结构示意图:
第二种Factory模式的应用并不是只是为了封装对象的创建,而是要把对象的创建放到子类中实现:Factory中只是提供了对象创建的接口,其实现将放在Factory的子类ConcreteFactory中进行。这是2和1的区别所在。第二种实现代码大致如下,C++版
//Factory.h
#ifndef _FACTORY_H_
#define _FACTORY_H_
class Product;
class Factory
{
public:
virtual ~Factory() = 0;
virtual Product* CreateProduct() = 0;
protected:
Factory();
private:
};
class ConcreteFactory:public Factory
{
public:
~ConcreteFactory();
ConcreteFactory();
Product* CreateProduct();
protected:
private:
};
#endif //~_FACTORY_H_
//main.cpp
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
Factory* fac = new ConcreteFactory();
Product* p = fac->CreateProduct();
return 0;
}
至于main中delete fac还可以接受,如果delete p觉得不爽的话请大胆使用shard_ptr吧。
在实现中我们可以通过参数化工厂方法,即给FactoryMethod()传递一个参数用以决定创建具体哪一个具体的Product。
ps:突然想到基类虚析构用了好久,但为啥现在居然想不清楚了,这是弱爆了,现记录下:基类析构函数设为virtual,则派生类的析构函数将自动为virtual,(虽然名字不一样,我一直纠结在这),当delete pBase时,由于多态,将调用CChild::~CChild(),保证释放子类资源避免内存泄露。
扩展:构造函数为什么不能是virtual:虚函数采用一种虚调用的办法,虚调用是一种可以在只有部分信息的情况下工作的机制,特别允许我们调用一个只知道接口而不知道
其准确对象类型的函数。但如果要创建一个对象,你势必要知道对象的准确类型,因此构造函数不能为虚。