Factory模式,属于创建型模式,它主要是定义了一个创建对象接口,而让子类决定具体的实例化哪一个类。
参与者:
- Product: 主要定义工厂方法要创建对象的接口(C++ 中表现为虚函数)
- ConcreteProduct: 实现Product类的接口
- Factory: 主要声明一个工厂方法,这个方法返回Product类型的对象。这个方法可返回一个缺省实现,返回一个ConcreteProduct对象
- ConcreteFactory: 主要重定义Factory中工厂方法以返回一个具体的ConcreteProduct对象。
适用性:
1. 当一个类不知道它所必须创建的对象的类的时候
2. 当一个类希望由它的子类来指定它所创建的对象的时候
3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者局部化的时候
这里引用自《设计模式:可复用面向对象软件的基础》
翻译成简单点的话就是由一个类来创建另一个类或者它的子类。
书上的例子是创建迷宫,我们这里来一个简单的例子。
有一个产品,它有ABC三个系列,那么这里我们是创建一个Product类,主要来声明统一的接口,然后创建ConcreteProductA、ConcreteProductB、ConcreteProductC类,它们都继承Product类,这三个类是具体的ABC三个系列产品。
class Product
{
public:
Product(){};
virtual ~Product(){};
virtual void show() = 0;
};
class ConcreteProductA:public Product
{
public:
ConcreteProductA(){};
virtual ~ConcreteProductA(){};
virtual void show() override
{
printf("ConcreteProductA::show()\n");
}
};
class ConcreteProductB :public Product
{
public:
ConcreteProductB () {};
virtual ~ConcreteProductB() {};
virtual void show() override
{
printf("ConcreteProductB::show()\n");
}
};
class ConcreteProductC :public Product
{
public:
ConcreteProductC(){};
virtual ~ConcreteProductC (){};
virtual void show() override
{
printf("ConcreteProductC::show()\n");
}
};
然后我们创建工厂类—Factory类,客户只要直接操作工厂类就可以创建Product。
typedef enum _ProductID
{
ProductA,
ProductB,
ProductC
}ProductID;
class Factory
{
public:
Factory(){};
virtual ~Factory(){};
protected:
virtual Product* CreatProduct(ProductID id)
{
switch (id)
{
case ProductA:
return new ConcreteProductA();
default:
break;
}
return nullptr;
}
};
class ConcreteFactory :public Factory
{
public:
ConcreteFactory(ProductID id) :m_id(id), m_pProduct(nullptr)
{
}
virtual ~ConcreteFactory()
{
if (m_pProduct != nullptr)
delete m_pProduct;
}
//Lazy Initialization
Product* GetProduct()
{
if (m_pProduct == nullptr)
return m_pProduct = CreatProduct(m_id);
else
return m_pProduct;
}
protected:
virtual Product* CreatProduct(ProductID id) override
{
switch (id)
{
case ProductB:
return new ConcreteProductB();
case ProductC:
return new ConcreteProductC();
default:
break;
}
return Factory::CreatProduct(id);//Call if all other fail
}
private:
Product* m_pProduct;
ProductID m_id;
};
上面的工厂代码,构造器只是将产品初始化为0,而不是创建了具体的产品,当客户需要访问该产品的时候,首先要先确定产品的存在,如果不存在,则创建它。这种技术有时成为Lazy Initialization。
上面的工厂代码中,使用了参数化的工厂方法,在后期增加新的产品的时候,只需要更新产品标识(ProductID)和继承ConcreteFactory 类,并重写CreatProduct方法即可。这里最重要的操作就是在最后一定要调用父类的createproduct方法。