《软件设计精要与模式》之Factory Method模式
Factory Method模式是应用最为广泛的设计模式,毕竟他负责了一系列对象的创建,而对象的创建正是面向对象编程中最为繁琐的行为。《设计模式》一书写到,“Factory Method模式使一个类的实例化延迟到子类。”准确的说,Factory Method模式是将创建对象实例的责任,转移到了工厂类中,并利用抽象原理,将实例化行为延迟到具体工厂类。
"嫁祸江东"之计
在面向对象的设计中,对象的管理是其核心所在,其中,对象的创建是对象管理的第一步。对象的创建非常简单,在C#中,只需使用new操作符调用对象的构造方法即可,因此,管理对象最重要的是掌握创建对象的时机。
我们首先从对象的特征来看。代表抽象意思的类型,如接口和抽象类,是不能创建对象实例的,这意味着我们要创建的对象都是与对象类型有关。也就是说,对象的创建工作必然涉及到设计中的实现细节,从而导致创建者与具体的被创建这之间耦合度增强。举例来说,如果在一个项目中需要创建一些图形对象,例如Circle,Square图形,它们的结构如下图所示。
这个类结构非常符合面向对象思想,他通过IShape接口将Square和Circle对象抽象出来。根据多态的原理,我们可以在程序中利用IShape接口代替具体的Square和Circle类,从而将具体的对象类型绑定留到运行时,但由于接口对象是不能创建的,一旦项目需求创建IShape类型的对象,就必然要针对具体的类对象进行创建操作。例如:
![](/Images/OutliningIndicators/None.gif)
如果是开发一个图形工具,诸如Square和Circle之类对象的创建工作必然非常频繁。可以设想,在这个项目的各个摸块中,如果大量充斥着如上代码行,那么导致的结果是各个模块无法与Square具体对象解耦。当我们需要改变创建的对象为Circle时,就必须修改所以调用new Square()操作的模块。这无疑加大了修改的工作量,同时也导致了项目的不可扩展性,以及模块的不可重用性;而对于图形对象的抽象IShape接口来说,也成为了不必要且失败的设计。
我们的目的是要将这种变化给项目带来的灾难枪杀在摇篮之中,此时就需要利用“封装变化”的原理。我们可以引入Factory Method模式对对象的创建行为进行封装。IShape类型的对象是工厂要生产的产品。在Factory Method模式中,工厂对象的结构应与产品的结构平行,并与之一一对应。既然具体的产品对象有两种,相对应的具体工厂对象也应该是两个,既SquareFactory和CircleFactory;同时,还应该为这两个工厂抽象出一个共同的工厂接口IShapeFactory。
实现代码如下:
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/assets/blank.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/assets/blank.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
7
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/None.gif)
10
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/assets/blank.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/assets/blank.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/assets/blank.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
19
![](/Images/OutliningIndicators/None.gif)
20
![](/Images/OutliningIndicators/None.gif)
21
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/assets/blank.gif)
22
![](/Images/OutliningIndicators/InBlock.gif)
23
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/assets/blank.gif)
24
![](/Images/OutliningIndicators/InBlock.gif)
25
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/assets/blank.gif)
26
![](/Images/OutliningIndicators/InBlock.gif)
27
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
28
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
29
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
30
![](/Images/OutliningIndicators/None.gif)
31
![](/Images/OutliningIndicators/None.gif)
Factory Method模式实现了对象的创建封装,将创建具体产品对象的代码全部转移到了各自的工厂对象中,并在CreateShape方法中实现,整个结构如下图:
CreateShape方法的返回对象是IShape接口类型,这就有效地避免了工厂对象与具体产品对象的依赖,使得创建者与被创建者实现了解耦.
我想,真正的智者是不会被表象所迷惑的.事实上,Factory Method模式的引入,是一种"嫁祸江东"的伎俩,他依旧无法摆脱的职责转交给工厂对象,然而在工厂类的结构中,依旧存在具体的工厂类对象.我门解出了模块与具体图象的依赖,却又增加了对具体工厂对象的依赖,这会给我们的设计带来何种益处?
让我们从对象的创建频率来分析.对于一个图形分析工具而言,IShape对象的创建无疑是频繁的,最大的可能行就在这个项目的各个模块中都可能存在创建IShape对象的需要.工厂对象则不尽然,我门完全可以集中一个模块中,初始化该工厂对象,并在需要IShape对象的时候,直接调用工厂实例CreateShape方法就可以达到目的.
因此,引入工厂对象并不是简单的为产品建立相应的工厂,而是要注意划分各个模块的职责,将工厂对象的创建放到合适的地方。最佳方案莫过于将创建工厂对象的职责集中起来,放到一个模块中;而不是在需要创建产品时,才创建工厂对象。错误的例子是在创建产品时将工厂对象的创建与产品对象的创建放在一起,然后分布在各个模块中。这对于引入Factory Method模式来说,无非是画蛇添足。
示例代码下载:FactoryMetod.rar
《软件设计精要与模式》之Factory Method模式相关推荐
- adapter为null_软件设计精要之——适配器(Adapter)模式
1.问题背景 Adapter模式解决的问题在生活中经常会遇到:比如我们有一个Team为外界提供S类服务,但是我们Team里面没有能够完成此项任务的member,然后我们得知有A可以完成这项服务(这项任 ...
- 《软件设计精要与模式》前言
缘起 用过去几年互联网上最酷,而在当下已经被用滥的名词来说,我在2004年成为了一名博客,用日志的方式记录自己成长的经历.坦白说,技术的成长远远比身体的发育更加地艰辛与缓慢,尤其是当今信息爆炸的年代, ...
- 教你如何阅读本书,如何学好软件设计——软件设计精要与模式前言
前 言 缘起 用过去几年互联网上最酷,而在当下已经被用滥的名词来说,我在2004年成为了一名博客,用日志的方式记录自己成长的经历.坦白说,技术的成长远远比身体的发育更加地艰辛与缓慢,尤其是当今信 ...
- 《软件设计精要与模式》第二版源代码
<软件设计精要与模式>第二版的代码相较于第一版而言,做了一定的修改.代码采用C#语言编写,并在Windows XP, Visual Studio 2008, SQL Server 2005 ...
- 踏上《软件设计精要与模式》第二版的征途
距离<软件设计精要与模式>的出版已有两年多的时间,从出版之初的热销到后来归于平淡,我也经历了从兴奋期到蛰伏期的过程.这本书的反应不算好,也不算坏.在浩瀚如大海一般的书市里,就好似一滴水珠融 ...
- 《软件设计精要与模式》推荐序三
微软MVP InfoQ中文站.NET社区首席编辑 朱永光 很早就在博客园上拜读过张逸的文章,尤其对他在设计模式方面的经验和见解印象深刻.在我把他邀请进InfoQ中文站编辑团队后,经过深入而频繁的交流, ...
- [书籍推荐]《软件设计精要与模式(第2版)》-张逸——提高设计模式及软件设计的方法...
<软件设计精要与模式(第2版)>是园子里张逸大大今年4月出版的关于软件设计及设计模式方面的书,我是5月下旬到手,每天晚上看一章,断断续续的到昨天晚上总算把全书28章看完了,感受很深,以往在 ...
- Builder Design模式和Factory Design模式之间有什么区别?
Builder设计模式和Factory设计模式有什么区别? 哪一个更有利,为什么? 如果我想测试和比较/对比这些模式,如何将我的发现表示为图形? #1楼 建筑商和抽象工厂 在某种程度上,Builder ...
- 设计模式--工厂方法(Factory Method)模式
模式定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类,使得一个类的实例化延迟到子类 类图 应用场景 1.当你不知道该使用对象的确切类型的时候: 2.当你希望为库或框架提供扩展其内部组件的方法 ...
最新文章
- Core Animation1-简介
- 【撸啊撸 Docker】搭建 Jenkins
- sql的split()函数
- 隹悦服务器批量控制软件
- 1.6 万亿参数你怕了吗?谷歌大脑语言模型速度是 T5 速度的 7 倍
- angularjs学习:通信
- Excel对比重复项
- C++设计模式:UML工具及常用符号
- Linux平台下rar, 7z, zip压缩文件密码破解
- 使用github遇到的问题及其解决方法汇总
- 人生「价值」的三个关键词|《价值》
- spark常用的linux命令,GitHub - Sparkinzy/linux-command: Linux命令大全搜索工具,内容包含Linux命令手册、详解、学习、搜集。...
- 抢先体验 Ubuntu 22.04 Jammy Jellyfish
- Mac宝藏软件推荐(笔者也在用)(二)
- 蓝牙BLEBLEcc2540开启广播的过程
- Trinity使用流程
- 业务中台和数据中台的区别
- Ubuntu解压缩命令详解
- 钱多多软件制作第二天
- 细分市场或成为OA产品同质化的救星|企服三会系列报道