工厂对象模式简介

工厂对象模式简介

在GoF的《设计模式》一书中,对Factory Method/Object Method 意图描述如下:

定义一个用于创建对象的接口,让子类决定实例化是哪一个类。 Factory Metho是一个类的实例化延迟到其子类。

其结构图如下:

其中, 类 Product 定义了一类对象的接口。 ConcreteProduct 实现 Product 的接口。 Creator是工厂方法的包装器。ConcreteCreator 类实现Creator的接口。基于以上结构,每个ConcreteProduct必须带有一个 ConcreteCreator, 用来产生特定的ConcreteProduct。

这种实现的缺点,在《设计模式》一书中也提到过一点 是客户可能仅仅想创建一个特定的 ConcreteProduct 对象,但必须额外创建 Creator 的子类。 在ConcreteProduct 的演化上造成额外的工作量。 另一点从代码简洁之道角度来看,每一个 ConcreteCreator 的实现都几乎一样,就像一幕幕乏味的样板戏,简直就是鸡肋。

那么如何改进呢?

用boost factory & boost function实现对象工厂

文件:ObjectFactory.h

[cpp] view plain copy

  1. #ifndef MP_OBJECT_FACTORY_H
  2. #define MP_OBJECT_FACTORY_H
  3. #include <boost/function.hpp>
  4. #include <map>
  5. /// 工厂模式泛型实现.
  6. /// 限制: 生成的对象必须为通过默认构造函数来构造.
  7. /// 当然你也可以扩展这个模板让它支持更多参数的构造函数.
  8. template<typename IdType, typename ObjectType>
  9. class ObjectFactory
  10. {
  11. public:
  12. /// 表示默认构造函数的函数对象.
  13. typedef boost::function< ObjectType* () > CreatorType;
  14. /// 构造函数对应的函数对象的关联容器.
  15. typedef std::map<IdType, CreatorType> ObjectCreator_map;
  16. /// 注册子类对象的构造函数信息.
  17. void RegisterObjectCreator(const IdType& id, const CreatorType &creator)
  18. {
  19. objectCreatorMap_[id] = creator;
  20. }
  21. /// 通过默认构造函数在堆上创建一个新的对象实例. 使用new生成.
  22. ObjectType * MakeObject(const IdType& id)
  23. {
  24. ObjectCreator_map::const_iterator iter = objectCreatorMap_.find(id);
  25. if (iter == objectCreatorMap_.end())
  26. {
  27. return NULL;
  28. }
  29. else
  30. {
  31. return (iter->second)();
  32. }
  33. }
  34. private:
  35. ObjectCreator_map objectCreatorMap_;
  36. };
  37. #endif

以上代码中,模板ObjectFactor接收两个参数,第一个参数IdType是用来标识是哪种子类对象的关键字。ObjectType是基类对 象类型。也就是上面结构图中的Product。为了实现创建ConcreteProduct对象的方法,我们需要获得每个子类对象的构造函数信息,通过 RegisterObjectCreator方法我们将子类对象的构造函数信息保存在工厂中。  那么哪种数据结构表示构造函数信息呢? 通过普通函数指针,好像行不通。在这里我们用到了 boost::function,它可以将任意的函数信息封装到function object对象中,从而可以实现赋值,调用等操作。

以上工厂实现中我们将任意类型的默认构造函数信息用 boost::function 进行封装,表示成 typedef boost::function< ObjectType* () > CreatorType;

后面我们就是建一张表来关联IdType与它所对应ConcreteProduct的构造函数信息。这里我们直接用 std::map关联容器来存储。

RegisterObjectCreator用于注册ConcreteProduct对象的构造函数信息。

MakeObject用于根据传入的IdType来生成对应的ConcreteProduct对象。注意这一句 (iter->second)(); 它返回指向ObjectType对象的指针。  实际上iter->second返回是一个CreatorType 类型函数对象,对一个函数对象进行()调用。因为CreatorType是对构造函数的封装,因此实际上是调用ConcreteProduct的构造函数 生成一个ConcreteProduct对象。 后面会看到 CreatorType 是我们用 boost::factory 封装的,它默认会调用new操作符从堆上构造一个ConcreteProduct对象。

如何使用对象工厂

我们来实现GoF Factory Method结构图中类似的代码。

首先我们定义几个类:

Product                  --  产品类接口封装,定义了类对象的接口。

ConcreteProductA  --  具体的产品A,该类 实现 Product 的接口。

ConcreteProductB  --  具体的产品B,该类 实现 Product 的接口。

文件:Product.h

[cpp] view plain copy

  1. #ifndef MP_PRODUCT_H
  2. #define MP_PRODUCT_H
  3. #include <boost/shared_ptr.hpp>
  4. class Product
  5. {
  6. public:
  7. explicit Product() {};
  8. virtual ~Product() {};
  9. virtual void DoSomething() = 0;
  10. };
  11. typedef boost::shared_ptr<Product> Product_ptr;
  12. #endif

文件:ConcreteProductA.h

[cpp] view plain copy

  1. #ifndef MP_CONCRETE_PRODUCT_A_H
  2. #define MP_CONCRETE_PRODUCT_A_H
  3. #include <iostream>
  4. class ConcreteProductA
  5. :public Product
  6. {
  7. public:
  8. void DoSomething()
  9. {
  10. std::cout<<__FUNCTION__<<std::endl;
  11. }
  12. };
  13. #endif

文件:ConcreteProductB.h

[cpp] view plain copy

  1. #ifndef MP_CONCRETE_PRODUCT_B_H
  2. #define MP_CONCRETE_PRODUCT_B_H
  3. #include <iostream>
  4. class ConcreteProductB
  5. :public Product
  6. {
  7. public:
  8. void DoSomething()
  9. {
  10. std::cout<<__FUNCTION__<<std::endl;
  11. }
  12. };
  13. #endif

下面我们来测试上面的对象工厂。

文件: Main.cpp

[cpp] view plain copy

  1. #include "Product.h"
  2. #include "ConcreteProductA.h"
  3. #include "ConcreteProductB.h"
  4. #include "ObjectFactory.h"
  5. #include <string>
  6. #include <boost/functional/factory.hpp>
  7. int main(int argc, char **argv)
  8. {
  9. ObjectFactory<std::string, Product> productFactory; // 对象工厂
  10. // 注册对象构造器.
  11. productFactory.RegisterObjectCreator("PRODUCT_A", boost::factory<ConcreteProductA *>() );
  12. productFactory.RegisterObjectCreator("PRODUCT_B", boost::factory<ConcreteProductB *>() );
  13. //通过工厂生成对象, 存储在shared_ptr中.
  14. Product_ptr productA( productFactory.MakeObject("PRODUCT_A") );
  15. Product_ptr productB( productFactory.MakeObject("PRODUCT_B") );
  16. // 演示多态性质。
  17. productA->DoSomething();
  18. productB->DoSomething();
  19. return 0;
  20. }

在以上测试中,我们首先生成一个对象工厂,这里我们以std::string作为IdType来标示是哪种类型的ConcreteProduct。

然后向工厂中注册具体类的构造方法: productFactory.RegisterObjectCreator("PRODUCT_A", boost::factory<ConcreteProductA *>() ); 注意:这里用到了boost::factory,它可以将 new 表达式封装成函数对象(function object),  这也正式我们工厂的注册方法所需要的参数。

后面我们调用对象工厂的MakeObject来生成我们期望的ConcreteProduct对象。 我们用一个字符串来标识要生成哪种类型的ConcreteProduct对象。同时我们将返回的对象指针保存在 shared_ptr中,从而实现对象的自动管理。 类型Product_ptr的定义为: typedef boost::shared_ptr<Product> Product_ptr;  它是对Product接口的智能指针封装。

最后,就是展示多态行为的时候了,我们调用不同ConcreteProduct对象的DoSomething来演示。运行效果如下:

限制说明:

1. 本文只是实现了带有默认构造函数的对象工厂。 如果你愿意也可以实现带有多个参数构造函数的对象工厂。

2. ObjectFactory 也可以实现为Singleton模式,根据个人需要吧,本文的重点不在这里。

参考资料:

1.  《设计模式可复用面向对象软件的基础》/ Design Patterns:Elements of Reusable Object-Oriented software  GoF

2. 《C++_设计新思维》 / Modern C++ Design    Andrei Alexandrescu

3.  Boost.Functional/Factory document             Tobias Schwinger

4. Boost.Function document                              Douglas Gregor

时间: 2024-10-27 12:42:09

工厂对象模式简介的相关文章

设计模式(二)——工厂方法模式

设计模式(二)--工厂方法模式 一.工厂方法模式简介 1.工厂方法模式简介 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法将一个类的实例化延迟到其子类. 对每一个子类产品都分别对应一个工厂子类,用来创建相应的产品,若增加了新的产品,只需相应增加工厂子类即可. 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得工厂方法可以被子类继承. 工厂方法模式特点: (1)工厂方法模式是对简单工厂模式的稍微的改进.工厂方法模式的用意是定义一个

易学设计模式看书笔记(3) - 工厂方法模式

二.工厂方法模式 1.动物管理系统的例子 首先,抽象的动物类和具体的动物实现类: public interface Animal{ public void eat(); } public class Tiger implements Animal { public void eat(){ sysout.out.println("老虎会吃"); }; public void run(){ sysout.out.println("老虎会跑"); }; } public

Java进阶篇设计模式之十三 ---- 观察者模式和空对象模式

前言 在上一篇中我们学习了行为型模式的备忘录模式(Memento Pattern)和状态模式(Memento Pattern).本篇则来学习下行为型模式的最后两个模式,观察者模式(Observer Pattern)和空对象模式模式(NullObject Pattern). 观察者模式 简介 观察者模式又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependents)模式.观察者模式定义

Objective-C设计模式——工厂方法模式virtual constructor(对象创建)

工厂方法模式 工厂方法模式可以控制对象的创建过程,屏蔽对象创建的细节,可以直接创建出我们所需要的已经配置好的对象. 工厂方法模式定义了创建方法的接口,让子类决定实例化哪一个类,工厂方法模式使得一个类的实例化延迟到其子类. 工厂方法的工厂其实是多太的一个经典应用,而其生产的产品取决于使用什么工厂,符合面向对象设计的开放封闭原则,添加产品只需要添加新的类,而不需要修改原有的代码. 使用场景 1.编译时无法准确预期要创建的对象的类: 2.类想让其子类决定在运行时创见什么: 3.类有若干辅助类为其子类,

9、Cocos2dx 3.0游戏开发三查找值小工厂方法模式和对象

重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个经典的设计模式.指的是基类中仅仅定义创建对象的接口,将实际的实现推迟到子类中. 在这里.我们将它稍加推广,泛指一切生成并返回一个对象的静态函数. 一个经典的工厂方法如同这样: Sprite* factoryMethod() { Sprite* ret = new Sprite(); //在这里对 r

简单工厂模式--工厂方法模式(简介)

一.简单工厂模式(静态工厂) 简单工厂模式不属于23种标准设计模式 简单工厂模式是工厂方法模式的一个特殊的实现 简单工厂就是由一个工厂类根据传入的参数决定创建出哪一种产品类的实例  二.实现 产品接口或者抽象类 package factory; /* * 产品接口 */ public interface Product { //生产工艺 public void craftwork(); //产品类型 public void type(); } 实现的子类 package factory; /*

9、Cocos2dx 3.0游戏开发找小三之工厂方法模式与对象传值

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个经典的设计模式,指的是基类中只定义创建对象的接口,将实际的实现推迟到子类中. 在这里,我们将它稍加推广,泛指一切生成并返回一个对象的静态函数. 一个经典的工厂方法如同这样: Sprite* factoryMethod() { Sprite* ret = new Sprite(); //在这里对 ret

生成对象---工厂方法模式

问题 当代码运行时我们才知道要生成的对象类型(BlogApptEncoder或者MegaBlogApptEncoder) 我们需要能够相对轻松的加入一些新的产品类型(如一种新业务处理方式SyncMl) 每一个产品类型都可定制特定的功能(getHeaderText()和getFooterText()) 实现 <?php /* factory_method.php 工厂方法模式把创建者与要生产的产品类分离开, 创建者是一个工厂类,定义了用于生成产品对象的类方法, 如果没有提供默认实现,那就有创建者的

JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象. 在这些情况,新对象的建立就是一个 "过程",不仅是一个操作,像一部大机器中的一个齿轮传动. 模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实