设计模式——抽象工厂

2023-08-12  本文已影响0人  东方胖

抽象工厂的要点是
在 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 ,一棵产品树里每个节点都是一个类,同时具体的工厂对应每棵树也有一个类。

扩展时 新建一个工厂,新建产品 即可

总结

抽象工厂和工厂方法的区别。

上一篇 下一篇

猜你喜欢

热点阅读