IOS设计模式浅析之工厂方法模式(Factory Method)
概述
在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口。
如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对象”不随着需求的改变而改变,这就是本章要说的Factory Method模式了。
定义
“定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到其子类。”
- 最初的定义出现于《设计模式》(Addison-Wesley,1994)。
结构图

抽象产品Product(可以是接口或者抽象类)定义了工厂方法创建的对象的接口和产品的共性;ConcreteProduct实现了Product。Creator定义了返回Product类型对象的工厂方法;ConcreteCreator实现了Creator,返回具体的ConcreteProduct的实例。
从结构图可以看出,在工厂方法模式中,核心的工厂类(Creator)不再负责所有产品的创建,而是将具体创建工作交给子类(ConcreteCreator)去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节。与直接创建新的具体产品相比,工厂方法模式让客户程序可以要求由工厂方法创建的对象拥有一组共同的行为。这样往类层次结构中引入新的具体产品时,并不需要修改客户端代码,因为返回的任何具体对象的接口都跟客户端一直在用的从前的接口相同。从结构图也可以看到,工厂方法模式中的工厂类与产品类往往具有平行的等级结构,它们之间一一对应。
示例
根据工厂方法模式的定义和结构图,现在将简单工厂模式中的示例,用工厂方法模式来实现,先看使用工厂方法模式实现的结构图:

从图中可以看到,在简单工厂模式中,由工厂类(ChartFactory)根据参数负责创建具体的产品(线形图、饼状图);而在工厂方法模式中,工厂类(Factory)只定义了一个创建产品的抽象接口,创建具体产品的工作由具体的工厂(线形图工厂、饼状图工厂)来实现。如果需要增加其他类型的图形绘制,那么使用简单工厂模式实现的话,首先需要增加一个其他图形绘制的类,例如柱状图(BarChart),然后修改工厂类(ChartFactory),在里面加分支语句来判断;使用工厂方法模式实现的话,不仅需要增加图形绘制类,还需要增加具体工厂类(BarFactory)。看到这里,可能大家会感觉到,工厂方法模式不但没有减少难度,反而增加了一些类和复杂度。这样来看,是不是没有必要使用工厂方法模式?咱们再回顾一下开篇介绍的六大设计原则,有一个原则是“开放-关闭原则”,简单工厂模式不仅对扩展开放,而且对修改也开放,违反了“开放-关闭原则”。工厂方法模式是简单工厂模式的进一步抽象,它保持了简单工厂模式的优点(去除了客户端与具体产品的依赖),而且克服了它的缺点(违反开放-关闭原则”)。它的缺点是每增加一个产品,就需要加一个产品工厂的类,增加了额外的开发工作量。理论分析就到这里,接下来看看代码:
IChart.h:
@protocol IChart <NSObject> - (void)drawing;
LineChart.m(部分代码):
- (void)drawing
{
NSLog(@"LineChart drawing.");
}
PieChart.m(部分代码):
- (void)drawing
{
NSLog(@"PieChart drawing.");
}
Factory.h:
@protocol Factory <NSObject> - (id<IChart>)createChart;
LineFactory.m(部分代码):
- (id<IChart>)createChart
{ return [[[LineChartalloc] init] autorelease]; }
PieFactory. .m(部分代码):
- (id<IChart>)createChart
{ return [[[PieChartalloc] init] autorelease]; }
客户端调用代码:
id<Factory> factory = [[[LineFactoryalloc] init] autorelease];
// id<Factory> factory = [[[PieFactory alloc] init] autorelease];
id<IChart> chart = [factory createChart];
[chart drawing];
从调用代码可以看出,工厂方法模式从代码中消除了对应用程序特有类的耦合。代码秩序处理Product抽象接口(这里是id<IChart>),这样同一代码就可以复用。
思考
从上面的客户端调用代码看到,如果有多处调用绘图的地方,我们需要每处都进行修改,这样的话,实际上也没有达到我们的效果:应对变化,尽可能少的修改代码。那么该怎样处理这种情况呢?
下面一种方式可以做到:
// id<Factory> factory = [[[LineFactory alloc] init] autorelease];
// id<Factory> factory = [[[PieFactory alloc] init] autorelease];
id<Factory> factory = [[[NSClassFromString(@"PieFactory") alloc] init] autorelease]; id<IChart> chart = [factory createChart];
[chart drawing]; [NSNumber numberWithBool:YES];
这样的话,我们可以将@"PieFactory"放到配置文件中,当我们需要绘制线形图的时候,只需要修改配置文件即可,客户端的所有代码都不需要改变。
何时使用工厂方法模式
- 编译时无法准确预期要创建的对象的类;
- 类想让其子类决定在运行时创建什么;
- 类有若干辅助类为其子类,而你想将返回哪个子类这一信息局部化。
IOS设计模式浅析之工厂方法模式(Factory Method)的更多相关文章
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...
- 设计模式-03工厂方法模式(Factory Method Pattern)
插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...
- 【设计模式】工厂方法模式 Factory Method Pattern
在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...
- 二十四种设计模式:工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...
- 工厂方法模式-Factory Method(Java实现)
工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...
- 设计模式之工厂方法模式(Factory Method Pattern)
一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...
- 设计模式之 - 工厂方法模式 (Factory Method design pattern)
1. 模式意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...
- 大话设计模式--工厂方法模式 Factory Method -- C++实现
1. 工厂方法模式 定义一个用于创建对象的接口, 让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 和简单工厂模式相比: A: 简单工厂模式最大的优点在于工厂类中包含有必要的逻辑判断, ...
- 《JAVA设计模式》之工厂方法模式 (Factory)
在阎宏博士的<JAVA与模式>一书中开头是这样描述工厂方法模式的: 工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymor ...
随机推荐
- POJ 2010 - Moo University - Financial Aid 初探数据结构 二叉堆
考虑到数据结构短板严重,从计算几何换换口味= = 二叉堆 简介 堆总保持每个节点小于(大于)父亲节点.这样的堆被称作大根堆(小根堆). 顾名思义,大根堆的数根是堆内的最大元素. 堆的意义在于能快速O( ...
- VirtualBox中的虚拟机要如何设置,才能够上网
VirtualBox中有4种网络连接方式:1. NAT2. Bridged Adapter3. Internal4. Host-only Adapter 一般设置成NAT网路就可以,但是由于我在公司上 ...
- C# upnp
//获取Host Name var name = Dns.GetHostName(); Console.WriteLine("用户:" + name); //从当前Host Nam ...
- jquery学习--属性操作
学习jquery很长一段时间了,知道对属性操作的方式为: $("#xx1").attr("xx2"); //获取属性值 $("#xx1"). ...
- 【实(dou)力(bi)首(mai)发(meng)】第四次CCF软件能力认证题解
这次的题总体上相对前三次偏简单.由于实力有限,就分析前四题. 试题编号: 201503-1 试题名称: 图像旋转 时间限制: 5.0s 内存限制: 256.0MB 问题 ...
- String、StringBuffer、StringBuilder源码解读
序 好长时间没有认真写博客了,过去的一年挺忙的.负责过数据库.线上运维环境.写代码.Code review等等东西挺多. 学习了不少多方面的东西,不过还是需要回归实际.加强内功,方能扛鼎. 去年学习M ...
- 咏南IOCP中间件
咏南IOCP中间件 特大好消息,咏南中间件系列新增加——咏南IOCP中间件.咏南IOCP中间件完全兼容咏南DATASNAP中间件的远程方法接口. 中间件DELPHI7~DELPHI XE10.1.1都 ...
- css省略号
效果图如下: 效果图如下:
- 1055: [HAOI2008]玩具取名
Description 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后 他会根据自己的喜好,将名字中任意一个字母用"WING" ...
- 利用RBAC模型实现一个通用的权限管理系统
本文主要描述一个通用的权限系统实现思路与过程.也是对此次制作权限管理模块的总结. 制作此系统的初衷是为了让这个权限系统得以“通用”.就是生产一个web系统通过调用这个权限系统(生成的dll文件), 就 ...