声明:我发布本章节主要是和大家分享这本书里的知识点,如果涉及到了侵权请作者或是相关人士留言,我会删除。  
      Factory Method模式是应用最为广泛的设计模式,毕竟他负责了一系列对象的创建,而对象的创建正是面向对象编程中最为繁琐的行为。《设计模式》一书写到,“Factory Method模式使一个类的实例化延迟到子类。”准确的说,Factory Method模式是将创建对象实例的责任,转移到了工厂类中,并利用抽象原理,将实例化行为延迟到具体工厂类。

  "嫁祸江东"之计
  在面向对象的设计中,对象的管理是其核心所在,其中,对象的创建是对象管理的第一步。对象的创建非常简单,在C#中,只需使用new操作符调用对象的构造方法即可,因此,管理对象最重要的是掌握创建对象的时机。

  我们首先从对象的特征来看。代表抽象意思的类型,如接口和抽象类,是不能创建对象实例的,这意味着我们要创建的对象都是与对象类型有关。也就是说,对象的创建工作必然涉及到设计中的实现细节,从而导致创建者与具体的被创建这之间耦合度增强。举例来说,如果在一个项目中需要创建一些图形对象,例如Circle,Square图形,它们的结构如下图所示。
                                   
  这个类结构非常符合面向对象思想,他通过IShape接口将Square和Circle对象抽象出来。根据多态的原理,我们可以在程序中利用IShape接口代替具体的Square和Circle类,从而将具体的对象类型绑定留到运行时,但由于接口对象是不能创建的,一旦项目需求创建IShape类型的对象,就必然要针对具体的类对象进行创建操作。例如:

IShape shape=new Square();

  如果是开发一个图形工具,诸如Square和Circle之类对象的创建工作必然非常频繁。可以设想,在这个项目的各个摸块中,如果大量充斥着如上代码行,那么导致的结果是各个模块无法与Square具体对象解耦。当我们需要改变创建的对象为Circle时,就必须修改所以调用new Square()操作的模块。这无疑加大了修改的工作量,同时也导致了项目的不可扩展性,以及模块的不可重用性;而对于图形对象的抽象IShape接口来说,也成为了不必要且失败的设计。

  我们的目的是要将这种变化给项目带来的灾难枪杀在摇篮之中,此时就需要利用“封装变化”的原理。我们可以引入Factory Method模式对对象的创建行为进行封装。IShape类型的对象是工厂要生产的产品。在Factory Method模式中,工厂对象的结构应与产品的结构平行,并与之一一对应。既然具体的产品对象有两种,相对应的具体工厂对象也应该是两个,既SquareFactory和CircleFactory;同时,还应该为这两个工厂抽象出一个共同的工厂接口IShapeFactory。
                                 
实现代码如下:

 1namespace DonOfDesign.FactoryPattern.GraphicLib
 2{
 3    public interface IShapeFactory
 4    {
 5        IShape CreateShape();
 6    }
 7}
 8----------------------------------------------
 9namespace DonOfDesign.FactoryPattern.GraphicLib
10{
11    public class SquareFactory : IShapeFactory
12    {
13        public IShape CreateShape()
14        {
15            return new Square();
16        }
17    }
18}
19----------------------------------------------
20namespace DonOfDesign.FactoryPattern.GraphicLib
21{
22    public class CircleFactory : IShapeFactory
23    {
24        public IShape CreateShape()
25        {
26            return new Circle();
27        }
28    }
29}
30
31

Factory Method模式实现了对象的创建封装,将创建具体产品对象的代码全部转移到了各自的工厂对象中,并在CreateShape方法中实现,整个结构如下图:
         
      CreateShape方法的返回对象是IShape接口类型,这就有效地避免了工厂对象与具体产品对象的依赖,使得创建者与被创建者实现了解耦.
      我想,真正的智者是不会被表象所迷惑的.事实上,Factory Method模式的引入,是一种"嫁祸江东"的伎俩,他依旧无法摆脱的职责转交给工厂对象,然而在工厂类的结构中,依旧存在具体的工厂类对象.我门解出了模块与具体图象的依赖,却又增加了对具体工厂对象的依赖,这会给我们的设计带来何种益处?
      让我们从对象的创建频率来分析.对于一个图形分析工具而言,IShape对象的创建无疑是频繁的,最大的可能行就在这个项目的各个模块中都可能存在创建IShape对象的需要.工厂对象则不尽然,我门完全可以集中一个模块中,初始化该工厂对象,并在需要IShape对象的时候,直接调用工厂实例CreateShape方法就可以达到目的.
      因此,引入工厂对象并不是简单的为产品建立相应的工厂,而是要注意划分各个模块的职责,将工厂对象的创建放到合适的地方。最佳方案莫过于将创建工厂对象的职责集中起来,放到一个模块中;而不是在需要创建产品时,才创建工厂对象。错误的例子是在创建产品时将工厂对象的创建与产品对象的创建放在一起,然后分布在各个模块中。这对于引入Factory Method模式来说,无非是画蛇添足。

示例代码下载:FactoryMetod.rar

《软件设计精要与模式》之Factory Method模式相关推荐

  1. adapter为null_软件设计精要之——适配器(Adapter)模式

    1.问题背景 Adapter模式解决的问题在生活中经常会遇到:比如我们有一个Team为外界提供S类服务,但是我们Team里面没有能够完成此项任务的member,然后我们得知有A可以完成这项服务(这项任 ...

  2. 《软件设计精要与模式》前言

    缘起 用过去几年互联网上最酷,而在当下已经被用滥的名词来说,我在2004年成为了一名博客,用日志的方式记录自己成长的经历.坦白说,技术的成长远远比身体的发育更加地艰辛与缓慢,尤其是当今信息爆炸的年代, ...

  3. 教你如何阅读本书,如何学好软件设计——软件设计精要与模式前言

    前    言 缘起 用过去几年互联网上最酷,而在当下已经被用滥的名词来说,我在2004年成为了一名博客,用日志的方式记录自己成长的经历.坦白说,技术的成长远远比身体的发育更加地艰辛与缓慢,尤其是当今信 ...

  4. 《软件设计精要与模式》第二版源代码

    <软件设计精要与模式>第二版的代码相较于第一版而言,做了一定的修改.代码采用C#语言编写,并在Windows XP, Visual Studio 2008, SQL Server 2005 ...

  5. 踏上《软件设计精要与模式》第二版的征途

    距离<软件设计精要与模式>的出版已有两年多的时间,从出版之初的热销到后来归于平淡,我也经历了从兴奋期到蛰伏期的过程.这本书的反应不算好,也不算坏.在浩瀚如大海一般的书市里,就好似一滴水珠融 ...

  6. 《软件设计精要与模式》推荐序三

    微软MVP InfoQ中文站.NET社区首席编辑 朱永光 很早就在博客园上拜读过张逸的文章,尤其对他在设计模式方面的经验和见解印象深刻.在我把他邀请进InfoQ中文站编辑团队后,经过深入而频繁的交流, ...

  7. [书籍推荐]《软件设计精要与模式(第2版)》-张逸——提高设计模式及软件设计的方法...

    <软件设计精要与模式(第2版)>是园子里张逸大大今年4月出版的关于软件设计及设计模式方面的书,我是5月下旬到手,每天晚上看一章,断断续续的到昨天晚上总算把全书28章看完了,感受很深,以往在 ...

  8. Builder Design模式和Factory Design模式之间有什么区别?

    Builder设计模式和Factory设计模式有什么区别? 哪一个更有利,为什么? 如果我想测试和比较/对比这些模式,如何将我的发现表示为图形? #1楼 建筑商和抽象工厂 在某种程度上,Builder ...

  9. 设计模式--工厂方法(Factory Method)模式

    模式定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,使得一个类的实例化延迟到子类 类图 应用场景 1.当你不知道该使用对象的确切类型的时候: 2.当你希望为库或框架提供扩展其内部组件的方法 ...

最新文章

  1. 【VBA】点击工作簿中的每个单元格,整行整列变色
  2. Kubernetes初探:原理及实践应用
  3. PageRank算法以及Python实现(简洁版)
  4. 排序算法(1)—直接插入排序
  5. Tkinter之Label
  6. 8086除法指令DIV,IDIV
  7. android module 引用libs里面的so文件_Android中的JNI开发,你了解多少?
  8. C/C++判断是否为笔记本电脑
  9. keras中一个LSTM的具体例子
  10. Servlet过滤器Filter和监听器
  11. Codeproject文章翻译
  12. axure7 地址选择_Axure教程:省市县三级联动选择(全国省市区数据)
  13. 域名备案、公安网备案
  14. 转载:SpringBoot非官方教程 | 第二十四篇: springboot整合docker
  15. 测试war包(免费)
  16. 云服务器和虚拟主机有哪些区别
  17. ajax实现微博点赞功能
  18. 芬兰政府:要找到量子计算工业化的好时机
  19. Python爬虫-爬取手机应用市场中APP下载量
  20. WaterMark 1.0

热门文章

  1. 结合了人工客服和AI的Fin,可能是Siri最大的竞争对手
  2. 三星中文AI助手Bixby发布,现在,这是“一家AI商用技术公司”
  3. JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!
  4. Java 泛型 extends T 和 super T 详解
  5. 【Node全局变量global模块】
  6. 查看linux文件目录的大小和文件夹包含的文件数
  7. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库....
  8. 使用RequireJS优化Web应用前端
  9. Elasticsearch 嵌套类型nested
  10. MySQL基础之 标准模式通配符