C++设计模式之抽象工厂模式

问题描述

之前讲到了C++设计模式——工厂方法模式,我们可能会想到,后期产品会越来越多了,建立的工厂也会越来越多,工厂进行了增长,工厂变的凌乱而难于管理;由于工厂方法模式创建的对象都是继承于Product的,所以工厂方法模式中,每个工厂只能创建单一种类的产品,当需要生产一种全新的产品(不继承自Product)时,发现工厂方法是心有余而力不足。

举个例子来说:一个显示器电路板厂商,旗下的显示器电路板种类有非液晶的和液晶的;这个时候,厂商建造两个工厂,工厂A负责生产非液晶显示器电路板,工厂B负责生产液晶显示器电路板;工厂一直就这样运行着。有一天,总经理发现,直接生产显示器的其余部分也挺挣钱,所以,总经理决定,再建立两个工厂C和D;C负责生产非液晶显示器的其余部件,D负责生产液晶显示器的其余部件。此时,旁边参谋的人就说了,经理,这样做不好,我们可以直接在工厂A中添加一条负责生产非液晶显示器的其余部件的生产线,在工厂B中添加一条生产液晶显示器的其余部件的生产线,这样就可以不用增加厂房,只用将现有厂房进行扩大一下,同时也方便工厂的管理,而且生产非液晶显示器电路板的技术人员对非液晶显示的其余部件的生产具有指导的作用,生产液晶显示器电路板也是同理。总经理发现这是一个不错的主意。

再回到软件开发的过程中来,工厂A和B就是之前所说的C++设计模式——工厂方法模式;总经理再次建立工厂C和D,就是重复C++设计模式——工厂方法模式,只是生产的产品不同罢了。这样做的弊端就如参谋所说的那样,增加了管理成本和人力成本。在面向对象开发的过程中,是很注重对象管理和维护的,对象越多,就越难进行管理和维护;如果工厂数量过多,那么管理和维护的成本将大大增加;虽然生产的是不同的产品,但是可以二者之间是有微妙的关系的,如参谋所说,技术人员的一些技术经验是可以借鉴的,这就相当于同一个类中的不同对象,之间是可以公用某些资源的。那么,增加一条流水线,扩大厂房,当然是最好的主意了。

实际问题已经得到了解决,那么如何使用设计模式模拟这个实际的问题呢?那就是接下来所说的抽象工厂模式。

UML类图

现在要讲的抽象工厂模式,就是工厂方法模式的扩展和延伸,但是抽象工厂模式,更有一般性和代表性;它具有工厂方法具有的优点,也增加了解决实际问题的能力。

如图所示,抽象工厂模式,就好比是两个工厂方法模式的叠加。抽象工厂创建的是一系列相关的对象,其中创建的实现其实就是采用的工厂方法模式。在工厂Factory中的每一个方法,就好比是一条生产线,而生产线实际需要生产什么样的产品,这是由Factory1和Factory2去决定的,这样便延迟了具体子类的实例化;同时集中化了生产线的管理,节省了资源的浪费。

适用场合

工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组(有多个种类)相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。

代码实现

/*
** FileName   : AbstractFactoryPatternDemo
** Author    : Jelly Young
** Date     : 2013/11/19
** Description : More information
*/ 

#include <iostream>
using namespace std;

// Product A
class ProductA
{
public:
  virtual void Show() = 0;
};

class ProductA1 : public ProductA
{
public:
  void Show()
  {
    cout<<"I'm ProductA1"<<endl;
  }
};

class ProductA2 : public ProductA
{
public:
  void Show()
  {
    cout<<"I'm ProductA2"<<endl;
  }
};

// Product B
class ProductB
{
public:
  virtual void Show() = 0;
};

class ProductB1 : public ProductB
{
public:
  void Show()
  {
    cout<<"I'm ProductB1"<<endl;
  }
};

class ProductB2 : public ProductB
{
public:
  void Show()
  {
    cout<<"I'm ProductB2"<<endl;
  }
};

// Factory
class Factory
{
public:
  virtual ProductA *CreateProductA() = 0;
  virtual ProductB *CreateProductB() = 0;
};

class Factory1 : public Factory
{
public:
  ProductA *CreateProductA()
  {
    return new ProductA1();
  }

  ProductB *CreateProductB()
  {
    return new ProductB1();
  }
};

class Factory2 : public Factory
{
  ProductA *CreateProductA()
  {
    return new ProductA2();
  }

  ProductB *CreateProductB()
  {
    return new ProductB2();
  }
};

int main(int argc, char *argv[])
{
  Factory *factoryObj1 = new Factory1();
  ProductA *productObjA1 = factoryObj1->CreateProductA();
  ProductB *productObjB1 = factoryObj1->CreateProductB();

  productObjA1->Show();
  productObjB1->Show();

  Factory *factoryObj2 = new Factory2();
  ProductA *productObjA2 = factoryObj2->CreateProductA();
  ProductB *productObjB2 = factoryObj2->CreateProductB();

  productObjA2->Show();
  productObjB2->Show();

  if (factoryObj1 != NULL)
  {
    delete factoryObj1;
    factoryObj1 = NULL;
  }

  if (productObjA1 != NULL)
  {
    delete productObjA1;
    productObjA1= NULL;
  }

  if (productObjB1 != NULL)
  {
    delete productObjB1;
    productObjB1 = NULL;
  }

  if (factoryObj2 != NULL)
  {
    delete factoryObj2;
    factoryObj2 = NULL;
  }

  if (productObjA2 != NULL)
  {
    delete productObjA2;
    productObjA2 = NULL;
  }

  if (productObjB2 != NULL)
  {
    delete productObjB2;
    productObjB2 = NULL;
  }
}
(0)

相关推荐

  • 详解C#的设计模式编程之抽象工厂模式的应用

    这里首先以一个生活中抽象工厂的例子来实现一个抽象工厂,然后再给出抽象工厂的定义和UML图来帮助大家更好地掌握抽象工厂模式,同时大家在理解的时候,可以对照抽象工厂生活中例子的实现和它的定义来加深抽象工厂的UML图理解.抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例. 抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例. 举例阐述抽象工厂模式: 假如中国

  • 实例解析Java单例模式编程中对抽象工厂模式的运用

    定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 类型:创建类模式 类图: 抽象工厂模式与工厂方法模式的区别         抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象.他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构:而抽象工厂模式则是针对的多个产品等级结构.在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同

  • 举例讲解Python设计模式编程的代理模式与抽象工厂模式

    代理模式 Proxy模式是一种常用的设计模式,它主要用来通过一个对象(比如B)给一个对象(比如A) 提供'代理'的方式方式访问.比如一个对象不方便直接引用,代理就在这个对象和访问者之间做了中介 你先设想:一个对象提供rgb三种颜色值,我想获得一个对象的rgb三种颜色,但是我不想让你获得蓝色属性,怎么办? class Proxy(object): def __init__(self, subject): self.__subject = subject # 代理其实本质上就是属性的委托 def _

  • JavaScript设计模式之抽象工厂模式介绍

    抽象工厂模式说明 1. 工厂方法模式的问题: 在工厂方法模式里,创建类都需要通过 工厂类,如果要扩展程序,就必须修改工厂类,这违背了闭包原则,对扩展开放,对修改关闭:对于设计有一定的问题. 2. 如何解决:就要用到抽象工厂模式,就是对功能类单独创建工厂类,这样就不必修改之前的代码,又扩展了功能. 3. 工厂模式其实就是对 实现同一接口的 实现类 的 统一 工厂方式创建调用,但 javascript 没有接口这号东西,所以就去掉这一层 实现,但位功能类的成员及方法都应当一样; 抽象工厂源码例子 1

  • Java设计模式编程中的工厂方法模式和抽象工厂模式

    工厂方法模式 动机 创建一个对象往往需要复杂的过程,所以不适合包含在一个复合工厂中,当有新的产品时,需要修改这个复合的工厂,不利于扩展. 而且,有些对象的创建可以需要用到复合工厂访问不到的信息,所以,定义一个工厂接口,通过实现这个接口来决定实例化那个产品,这就是工厂方法模式,让类的实例化推迟到子类中进行. 目的 1. 定义一个接口,让子类决定实例化哪个产品. 2. 通过通用接口创建对象. 实现 1. 产品接口和具体产品很好理解. 2. 工厂类提供一个工厂方法,返回一个产品对象.但是这个工厂方法是

  • Python设计模式之抽象工厂模式

    python面向对象编程入门,我们需要不断学习进步 """抽象工厂模式的实现""" import random class PetShop: """宠物商店""" def __init__(self, animal_factory=None): """宠物工厂是我们的抽象工厂.我们可以随意设置.""" self.pet_fact

  • C# 设计模式系列教程-抽象工厂模式

    1. 概述 抽象工厂模式为一个产品家族提供了统一的创建接口.当需要这个产品家族的某一系列的时候,可以从抽象工厂中选出相对应的系列来创建一个具体的工厂类别. 2. 抽象工厂模式中的角色 2.1 抽象工厂(AbstractFactory):担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的. 2.2 具体工厂(ConcreteFactory):这个角色直接在客户端的调用下创建产品的实例.这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的. 2.3 抽象产品

  • javascript抽象工厂模式详细说明

    抽象工厂模式说明 1. 工厂方法模式的问题: 在工厂方法模式里,创建类都需要通过 工厂类,如果要扩展程序,就必须修改工厂类,这违背了闭包原则,对扩展开放,对修改关闭:对于设计有一定的问题.   2. 如何解决:就要用到抽象工厂模式,就是对功能类单独创建工厂类,这样就不必修改之前的代码,又扩展了功能.   3. 工厂模式其实就是对 实现同一接口的 实现类 的 统一 工厂方式创建调用,但 javascript 没有接口这号东西,所以就去掉这一层 实现,但位功能类的成员及方法都应当一样; 抽象工厂源码

  • PHP实现设计模式中的抽象工厂模式详解

    抽象工厂模式(Abstact Factory)是一种常见的软件设计模式.该模式为一个产品族提供了统一的创建接口.当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个 具体的工厂类. [意图] 抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类[GOF95] [抽象工厂模式结构图] [抽象工厂模式中主要角色] 抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口.通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类

  • 初次接触php抽象工厂模式(Elgg)

    想实现这样一个功能:开展一个网站邀请活动,然后参与者(owner)将推广的网站地址链接发给好友,好友点击链接后在网站注册成功,owner的邀请日志记录条数加1. 活动类 Activity 复制代码 代码如下: class Activity extends ElggEntity { private $strategy; //用于保存策略实例 public function __construction($guid) { ... $this->load($guid); //载入实体 } public

随机推荐