写在前面

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

在上篇笔记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. Spring配置AOP实现定义切入点和织入增强

    XML里的id=””记得全小写 经过AOP的配置后,可以切入日志功能.访问切入.事务管理.性能监测等功能. 首先实现这个织入增强需要的jar包,除了常用的 com.springsource.org.a ...

  2. 界面显示两个ListView

    1.List界面布局 <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:an ...

  3. js获取页面高度赋值给div

    <script type="text/javascript"> window.onload=function(){ map_width=document.body.cl ...

  4. P235 实战练习(集合类2)、摇奖程序和验证码(修改版)

    1.分别向Set集合以及List集合中添加“A”.“a”.“c”.“C”.“a”5个元素,观察重复值“a”能否在List集合以及Set集合中成功添加. package org.hanqi.practi ...

  5. 20160729noip模拟赛zld

    首先显然有多少个奇数,就有多少个回文串是最优的(没有奇数时构造一个回文串 然后有了k个“核心”,把剩下的字符顺序安排到这些的两侧,最后最短的回文串长度就是答案 #include<map> ...

  6. Rouh set 入门知识2(基础定义篇)

    接上一篇,简单说明一下知识库的关系,设K1=(U,S1)和K2=(U,S2)为知识库 1.如果IND(S1)=IND(S2),即U/IND(S1)=U/IND(S2),则知识库K1与知识库K2是等价的 ...

  7. IO网络模型

    多路处理模型MPM MPM是Apache2引入的一个概念,就是将结构模块化.把核心任务处理作为一个可插拔的模块,使其能针对不同的环境进行优化 在这个情况下,就诞生出了处理模式的概念 Prefork 实 ...

  8. 02 Redis关闭服务报错---(error) ERR Errors trying to SHUTDOWN. Check logs.

    127.0.0.1:6379> shutdown (error) ERR Errors trying to SHUTDOWN. Check logs. 1.在redis.conf中修改日志文件的 ...

  9. 恢复Windows 10自带的微软正黑字体

    突然发现  在word中 Microsoft JhengHei 字体没有了,一查在C:\windows\fonts\msjh.ttc文件还在. Windows Registry Editor Vers ...

  10. select下拉框左右变换

    效果图: 使用jQuery插件---multiselect2side做法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...