【设计模式攻略】创建型模式之Factory模式

概要
Factory模式在现代编程语言中应该也是使用最广泛的模式之一。Factory模式有很多变体,根据实际情况,实现形式多样。最常见的可能还是GOF中提出的Abstract Factory模式和Factory Method模式。本文只是从最基本的Facotry模式概念本身出发,看看抛开GOF提出的两种经典Factory模式不谈,现阶段常见Factory模式的实现形式,在后续的其他文章中会再跟大家重点讨论GOF提出的Abstract Factory和Factory Method这两种模式。
Factory模式,顾名思义,就是抽象和封装了实例化动作的工厂,提供尽可能统一的接口给用户,简化对象的实例化过程。

目的
用户可能忽略对象具体实例化的逻辑过程,通过调用统一的接口来进行对象实例化,同时解除调用方与具体对象间的耦合,使调用者只依赖于抽象。

实例
看一种最简单的Factory模式的实现,假设有一组对象ConcreteObjectAConcreteObjectB,Factory负责对象的实例化,类图

代码实现如下:
class AbstractObject {};

class ConcreteObjectA : public AbstractObject {};
class ConcreteObjectB : public AbstractObject {};
class ConcreteObjectNULL : public AbstractObject {};
    
class Factory {
public:
     AbstractObject* create_object(const string& type) {
          if (type == "A") {
               return new      ConcreteObjectA;
          } else if type == "B") {
               return new      ConcreteObjectB;
          }
          return new ConcreteObjectNULL;
     }
};
用户可以通过统一的方法create_object,指定类型来实例化相应的对象:
Factory factory;
AbstractObject* obj_A = factory.create_object("A");
AbstractObject* obj_B = factory.create_object("B");
为了让Factory类使用更简单,可以Singleton模式来包装Factory类,Singleton模式请参考我的上一篇文章:

虽然这种Factory模式的实现很简单,没什么技术含量,但在很多程序中还是会被经常用到,就因为两个字,简单!
也许有人会说,那如果每添加一种对象,就需要修改Factory类,在其中增加相应对象的创建,那不是违反了Open-Close原则?Open-Close原则请参考:
确实没错,那我们稍微改变下Factory的实现:

为每个具体对象构造一个相应的Factory,在基类Factory中创建一个map,维护所有需要的Factory,每个子类Factory在构造函数中把自己注册到factory map中,具体对象由其对应的Factory来负责创建(重写do_create方法),代码如下:
class Factory {
public:
     AbstractObject* create_object(const string& type) {
          std::map<string, Factory*>::iterator it;
          it = factory_map.find(type);
          if (it != factory_map.end()) {
               return factory_map[type]->do_create();
          }
          return factory_map["NULL"]->do_create();
     }
    
     void register_factory(const string& type, Factory* factory) {
          factory_map[type] = factory;
     }
private:
     virtual AbstractObject* do_create() = 0;
     static std::map<string, Factory*> factory_map;
};

class FactoryA :public Factory{
public:
     FactoryA() {
          register_factory("A", this);
     }
     virtual AbstractObject* do_create() {
          return new      ConcreteObjectA;
     }    
};

class FactoryB :public Factory{
public:
     FactoryB() {
          register_factory("B", this);
     }
     virtual AbstractObject* do_create() {
          return new      ConcreteObjectB;
     }    
};

class FactoryNULL :public Factory{
public:
     FactoryNULL() {
          register_factory("NULL", this);
     }
     virtual AbstractObject* do_create() {
          return new      ConcreteObjectNULL;
     }    
};

用户使用时,首先需要定义所有的Factory对象,然后通过Factory的create_object方法来创建相应对象:
FactoryA factory_A;
FactoryB factory_B;
FactoryNULL factory_NULL;
// 以上对象的定义一般作为全局对象定义在对应Factory类实现的cpp文件中
注意一般会用Singleton来包装Factory,使用更方便,这里为了简化实现过程,没有采用Singleton
Factory factory;
AbstractObject* obj_A = factory.create_object("A");
AbstractObject* obj_B = factory.create_object("B");
相较于第一种实现,当要增加具体对象ConcreteObjectC时,不再需要修改Factory类本身,只需要增加FactoryC,并在代码定义FactoryC类型的对象factory_C后就可以了,满足开闭原则的要求。

我开始曾描述第二种实现是改变了第一种Factory的实现,而没有说是改进。因为两种实现确实各有利弊,对于第二种实现虽然从OO设计的角度更理想,但是却也带来了一下问题:
1. 每个Factory必须在使用前都各自实例化
2. 实现变得更复杂
3. 没多一种对象需要增加一个新的Factory类
当然,在使用Java或其他语言实现时,可以避免一些C++实现的难点,让实现更简单。

应用
Factory模式是使用最广泛的设计模式之一,可以说稍微有点规模的程序里都充实着各种形式的Factory,当用C++来实现时,需要额外注意一些问题,比如如果需要对象销毁怎么做,对象生命周期的管理等等。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值