抽象工厂的要点是
在 context 中,我们不需要规定要创建那个具体的子类。
Provide and interface for creating families of related or dependent objects without specifying their concrete classes.
比如我们有一组产品
class AbstractProduct {
};
class ProductA: public AbstractProduct {
};
class ProductB: public AbstractProduct {
};
// 创建产品A、B的上下文
AbstractProduct * pa = new ProductA();
AbstractProduct * pb = new ProductB();
抽象工厂是要把上面的 new ProductA() 隐藏。通过工厂方法也可以做到,
上面的代码通过工厂方法变成下面这种调用方式,创建动作从接口出:
Factory* factory = new MyFactory;
fatory->createProductA();
大概如此
现在,
设想产品出现更复杂的分类,如,现在有另一系列的 AbstractProduct2出现
class AbstractProduct2
{
};
class Product2A : public AbstractProduct2
{
};
class Product2B : public AbstractProduct2
{
};
这组产品有不同的抽象,所以无法在上面的工厂方法中共享接口。
产品返回的 AbstractProduct * 类型。
继承树是另一棵。
所以,为了达到那个 隐藏 new ProductXXX();
的目的,我们不得不再为它创建另一个工厂 MyFactory2,这个工厂针对是系列2的产品。
于是创建产品2 代码可能是这样
Factory * factory = new MyFactory2;
factory->createProduct2A();
用工厂方法,我们对每个系列的产品可以定义一个工厂,哇,这应该是可行的。
现在,因为产品的树,每棵对应一个工厂,这样一系列的工厂诞生了,如果视工厂为一种“新的产品”,那么实际上我们使用工厂方法的时候,又凭空造出了一棵产品树,这些新产品还是用着暴露hardcode方式在context使用
ProductFactory* factory = new ProductFactory();
抽象工厂模式的想法是,对这种新的工厂树施以工厂方法。隐藏上面那种 new XXXFactory()的代码。
类似工厂方法,对工厂产品我们将抽象几个接口,然后具体的工厂在子类中实现之
class AbstractFactory
{
public:
AbstractProduct* createProduct() = 0;
AbstractProduct2* createProduct2() = 0;
};
class ProductFactory: public AbstractFactory
{
public:
AbstractProduct* createProduct() {
return new ProductA();
}
AbstractProduct2* createProduct2() {
return new Product2A();
}
};
client
ProductFactory factory;
createObject(&factory); // createObject(AbstractFactory &); 接口声明为如此,参数是个抽象工厂
在 createObject 内部则不再关心 factory到底是哪个具体的工厂,这样做到了在 createObject的实现具有一种抽象作用。
带了一些灵活性。
抽象工厂一般会带来大量的class ,一棵产品树里每个节点都是一个类,同时具体的工厂对应每棵树也有一个类。
扩展时 新建一个工厂,新建产品 即可
总结
抽象工厂和工厂方法的区别。
- 它们都试图将代码中那种 new XXX();具体指定的硬编码抽象成接口,对调用的上下文隐藏起来,带来一种修改不影响client的代码的效果
- 但是工厂方法一般只有一个产品系列,即被创建的类型一般就是一棵继承树,而抽象工厂不止一棵继承树
- 通常工厂方法的特点是 createObject(type) 或者, 创建一个工厂 factory = new ConceretFactory();然后用factory的 虚函数接口创建所需要产品。
而抽象工厂必有一个抽象的 Factory 作为某个创建函数的参数,然后把具体类型传入,在某个创建上下文中持有factory的句柄来操作,利用虚函数的特性来实现运行选择哪个工厂来创建。
网友评论