写在前面

为方便读者,本文已添加至索引

在上篇笔记Abstract Factory设计模式中,时の魔导士创建了一系列的FoodFactory,并教会了其中一名霍比特人theCook如何去createFood。于是,白雪公主和7个小霍比特人终于能填饱肚子了。但是,美丽的童话世界中一定有着危险潜伏。这时,我们需要有一名霍比特人勇敢地站出来守护善良的公主和她的小伙伴们。很好,就让我们叫他theWarrior,一位武器大师:精通匕首、剑、弓、魔杖甚至AK47……。正因如此,我们需要一个武器工厂生产一整套的装备供他使用。回顾上篇笔记的内容,时の魔导士自然想到抽象工厂的好主意,我们可以有SwordFactory, DaggerFactory, BowFactory......但是有个问题,createWeapon并不能像createFood那样将制作过程硬编码,因为theWarrior会需要不同的武器组合,比如英勇的战士一般配一把利剑和坚固的盾牌,或者像精灵王子莱格拉斯(出自电影:霍比特人2)那样带2把匕首和弓箭。怎么样才好呢?当然Factory Method!其实在抽象工厂篇中,我们已经用到Factory Method来实现抽象工厂了。现在让我们来看看具体的内容吧。

要点梳理

  • 目的分类

    • 对象创建型模式
  • 范围准则
    • 类(该模式处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了)
  • 主要功能
    • 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类
  • 适用情况
    • 当一个类不知道它所必须创建的对象的类的时候
    • 当一个类希望由它的子类来指定它所创建的对象的时候
    • 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候参与部分
  • 参与部分
    • Product:定义工厂方法所创建的对象的接口
    • ConcreteProduct:实现Product接口
    • Creator:声明工厂方法,该方法返回一个Product类型的对象。Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象;可以调用工厂方法以创建一个Product对象
    • ConcreteProduct:重定义工厂方法以返回一个ConcreteProduct实例
  • 协作过程
    • Creator依赖于它的子类来定义工厂方法,所以它返回一个适当的ConcreteProduct实例
  • UML图例

示例分析 - 强大的武器工坊

时の魔导士仔细思考了一番,决定先建造一座充满魔法的WeaponFactory,通过引入Factory Method,以使得其具体的子类可以选择这些构件,装配出一套适合theWarrior的武器。我们来看一下这个示例:

 class WeaponFactory {
public:
void getWeapon(WeaponSuite* suite); //Factory method:
virtual Weapon* createWeapon() { return 0; }
} void WeaponFactory::getWeapon(WeaponSuite* suite) {
Weapon* w = createWeapon();
suite->add(w);
}

于是我们可以引入一个名为『战士的荣耀』的长剑工厂(Kimi: 是不是很酷!……):

 class HonorOfFighter : public WeaponFactory {
public:
HonorOfFighter();
Weapon* createWeapon() { return new Sword(); }
}

或者一个名为『卫士的信仰』的盾牌工厂,等等等等:

 class BliefOfDefender : public WeaponFactory {
public:
BliefOfDefender();
Weapon* createWeapon() { return new Shield(); }
}

为了更清楚地表示上面所说的模型,让我们来看看UML图:

哈哈,这下勇敢的霍比特人就能通过拜访不同的工厂来自由获取自己的战斗武器了。

特点总结

我们来总结下工厂方法模式的特点:

  1. 工厂方法不再将与特定应用有关的类绑定到我们的代码中。代码仅处理Product接口;因此它可以与用户定义的任何ConcreteProduct类一起使用。
  2. 为子类提供挂钩(hook)。用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。
  3. 潜在缺点在于我们可能仅仅为了创建一个特定的ConcreteProduct对象,就不得不创建Creator的子类。

当然,如我最早的笔记中所说,设计模式固然重要,但绝不可照本宣科。不同的设计模式之间往往存在着相互依赖,相辅相成的微妙关系。正如前篇中的Abstract Factory,通常会使用Factory Method来实现,当然也可以用Prototype,只是我们暂时还没有涉及。

抽象工厂模式和工厂方法模式从设计模式的角度来讲,的确是存在差异的。但是在我的这两篇笔记中,有的朋友可能会觉得我的示例中都同时存在着抽象工厂模式和工厂方法模式。没错,但是请还是根据文章的内容,辩证地来看待。

写在最后

今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!

[学习笔记]设计模式之Factory Method的更多相关文章

  1. 设计模式C++学习笔记之五(Factory Method工厂方法模式)

      工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的 ...

  2. [学习笔记]设计模式之Abstract Factory

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在上篇笔记Builder设计模式中,时の魔导士祭出了自己的WorldCreator.尽管它因此能创造出一个有山有树有房子的世界,但是白 ...

  3. [学习笔记]设计模式之Bridge

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 “魔镜啊魔镜,谁是这个世界上最美丽的人?”月光中,一个低沉的声音回荡在女王的卧室.“是美丽的白雪公主,她正和小霍比特人们幸福快乐地生活 ...

  4. [学习笔记]设计模式之Prototype

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在笔记Builder模式中,我们曾见到了最初用于创建平行世界的函数createWorld,并且它是Mage类的成员函数(毕竟是专属于魔 ...

  5. [学习笔记]设计模式之Chain of Responsibility

    为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 最近时间比较紧,所以发文的速度相对较慢了.但是看到园子里有很多朋友对设计模式感兴趣,我感觉很高兴,能够和大家一起学习这些知识. 之前的 ...

  6. [学习笔记]设计模式之Singleton

    写在前面 为方便读者,本文已添加至索引: 设计模式 魔法手札索引 在前几篇笔记中,我们有了解了部分对象创建型模式,包括Builder(建造者).Abstract Factory(抽象工厂)和Facto ...

  7. [学习笔记]设计模式之Facade

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 Facade(外观)模式定义了一个高层接口,它能为子系统中的一组接口提供一个一致的界面,从而使得这一子系统更加容易使用.欢迎回到时の魔 ...

  8. [学习笔记]设计模式之Builder

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 作为一个新入职的魔导士呢,哦不,是程序员,我以为并没有太多机会去设计项目的软件架构.但是,工作一段时间之后,自己渐渐意识到,哪怕是自己 ...

  9. [学习笔记]设计模式之Adapter

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 Adapter(适配器)模式主要解决接口不匹配的问题.为此,让我们要回到最初Builder模式创建平行世界时,白雪公主和小霍比特人的谜 ...

随机推荐

  1. python 三分钟入门

    1.Python环境配置(2.7版本): Python官网:https://www.python.org/ Pycharm官网 http://www.jetbrains.com/pycharm/dow ...

  2. 数据添加到DataTable

    DataTable tblDatas = new DataTable("Datas");            DataColumn dc = null;              ...

  3. asp.net MVC FileResult在IE下异常的解决办法

    var encoding = System.Text.Encoding.UTF8; Response.Charset = encoding.WebName; Response.HeaderEncodi ...

  4. Coding.net代码托管平台建立WordPress

    Coding.net这是一个国内新兴的代码托管平台,功能主要包括:代码托管.在线运行环境.监控代码质量,兼有一定的社交功能,在线运行环境支持Java.Ruby.Node.js.PHP.Python.G ...

  5. 数据采集服务提供商,ip提供商 里面有些不错的基础数据

    http://user.qzone.qq.com/1649677458 这家公司的爬虫应该挺牛的 !@#!#!~#¥¥¥@@http://www.site-digger.com/

  6. PHP错误Warning: Cannot modify header information - headers already sent by解决方法

    这篇文章主要介绍了PHP错误Warning: Cannot modify header information - headers already sent by解决方法,需要的朋友可以参考下 今天在 ...

  7. .h头文件、 .lib库文件、 .dll动态链接库文件之间的关系

    转自.h头文件. .lib库文件. .dll动态链接库文件之间的关系 h头文件作用:声明函数接口 dll动态链接库作用:含有函数的可执行代码 lib库有两种: (1)静态链接库(Static Liba ...

  8. 基于Spring Boot构建的Spring MVC快速入门

    原文地址:http://tianmaying.com/tutorial/spring-mvc-quickstart 环境准备 一个称手的文本编辑器(例如Vim.Emacs.Sublime Text)或 ...

  9. CCS3.3之DM642开发环境建立

    使用的仿真器是SEED-XDSUSB2.0/5V. 之前用的是CCS2.2,换成了CCS3.3的. 1.安装CCS3.3.38.在我安装完后,并没有急着升级,升级的程序是SR12_CCS_v3.3_S ...

  10. oracle构建一致性读

    对于实际的业务系统,通常有一些热点的表,insert和delete的量非常大,这个时候就会发现一些查询语句的逻辑读比较偏高,这时可能就是oracle在构建一致性块的进行的consistent read ...