前面一篇展示了一个简单工厂模式,这一篇主要是对比,工厂方法模式比简单工厂模式好在哪里?为什么要用这个模式?这个模式的精髓在哪里?

就以计算器为例,结果图如下:

加减乘除运算都是继承自基类运算类,然后工厂类来调用这些运算,创建相应的对象,从而进行操作,oc代码如下:

基类:

#import <Foundation/Foundation.h>

@interface ZYCount : NSObject
@property (nonatomic, assign) double numberA;
@property (nonatomic, assign) double numberB;
- (instancetype)initWithNumberA:(double)numberA numberB:(double)numberB; /**
* 由于不知道子类的具体运算,所以,这个方法交给子类去实现即可(又由于此方法,所有子类都会有此一次运算,而不是某个子类所特有的,所以放到基类里最合适)
*
*/
- (double)resultForCount;
@end #import "ZYCount.h" @interface ZYCount ()
@end @implementation ZYCount
- (instancetype)initWithNumberA:(double)numberA numberB:(double)numberB
{
if (self = [super init]) {
_numberA = numberA;
_numberB = numberB;
}
return self;
} @end

加法类:

#import "ZYCount.h"

@interface ZYCountAdd : ZYCount
@end #import "ZYCountAdd.h" @implementation ZYCountAdd
- (double)resultForCount
{
return self.numberA + self.numberB;
}
@end

减法类:

#import "ZYCount.h"

@interface ZYCountSubtractor : ZYCount

@end

#import "ZYCountSubtractor.h"

@implementation ZYCountSubtractor
- (double)resultForCount
{
return self.numberA - self.numberB;
}
@end

乘法类:

#import "ZYCount.h"

@interface ZYCountMuli : ZYCount

@end

#import "ZYCountMuli.h"

@implementation ZYCountMuli
- (double)resultForCount
{
return self.numberA * self.numberB;
}
@end

除法类:

#import "ZYCount.h"

@interface ZYCountDivision : ZYCount

@end

#import "ZYCountDivision.h"

@implementation ZYCountDivision
- (double)resultForCount
{
if (self.numberB == 0) {
NSLog(@"除数为0,产出错误");
return 0;
}
return self.numberA / self.numberB;
}
@end

工具类:

#import <Foundation/Foundation.h>

@class ZYCount;

@interface ZYCountTool : NSObject
+ (ZYCount *)creatCountForOperation:(NSString *)operationStr;
@end #import "ZYCountTool.h"
#import "ZYCountAdd.h"
#import "ZYCountSubtractor.h"
#import "ZYCountMuli.h"
#import "ZYCountDivision.h"
@implementation ZYCountTool
+ (ZYCount *)creatCountForOperation:(NSString *)operationStr
{
if ([operationStr isEqualToString:@"+"]) {
return [[ZYCountAdd alloc] init];
}
else if ([operationStr isEqualToString:@"-"]) {
return [[ZYCountSubtractor alloc] init];
}
else if ([operationStr isEqualToString:@"*"]) {
return [[ZYCountMuli alloc] init];
} return [[ZYCountDivision alloc] init];
}
@end

viewController里面的代码:

#import "ViewController.h"
#import "ZYCountAdd.h"
#import "ZYCountSubtractor.h"
#import "ZYCountMuli.h"
#import "ZYCountDivision.h"
#import "ZYCountTool.h"
@interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. ZYCountAdd *p = (ZYCountAdd *)[ZYCountTool creatCountForOperation:@"+"];
p.numberA = 10;
p.numberB = 20;
NSLog(@"%lf",[p resultForCount]);
} @end

从这样的结构来看,可以知道,当我想要增加需求,比如说,其m的n次方的时候,需要增加一个运算类的子类,然后还需要更改工具类里面的代码,使得其支持这样新的运算对象的生成。这样,不仅扩展是开放的,修改也开放了,违背了,“开放-封闭原则”。

而采用工厂方法模式,可以解决这个问题。除了viewController里面代码和工厂类的代码需要改动,运算类的代码是一样的

改动代码如下:

#import <Foundation/Foundation.h>

@class ZYCount;

@interface ZYCountTool : NSObject
+ (ZYCount *)createOperation;
@end #import "ZYCountTool.h"
@implementation ZYCountTool
@end
#import "ZYCountTool.h"

@interface ZYAddTool : ZYCountTool

@end

#import "ZYAddTool.h"
#import "ZYCountAdd.h" @implementation ZYAddTool
+ (ZYCount *)createOperation
{
return [[ZYCountAdd alloc] init];
}
@end
#import "ZYCountTool.h"

@interface ZYSubtractorTool : ZYCountTool

@end

#import "ZYSubtractorTool.h"
#import "ZYCountSubtractor.h"
@implementation ZYSubtractorTool
+ (ZYCount *)createOperation
{
return [[ZYCountSubtractor alloc] init];
}
@end
#import "ZYCountTool.h"

@interface ZYMuliTool : ZYCountTool

@end

#import "ZYMuliTool.h"
#import "ZYCountMuli.h"
@implementation ZYMuliTool
+ (ZYCount *)createOperation
{
return [[ZYCountMuli alloc] init];
}
@end
#import "ZYCountTool.h"

@interface ZYDivisionTool : ZYCountTool

@end

#import "ZYDivisionTool.h"
#import "ZYCountDivision.h" @implementation ZYDivisionTool
+ (ZYCount *)createOperation
{
return [[ZYCountDivision alloc] init];
}
@end

viewController里面的代码:

#import "ViewController.h"
#import "ZYCountAdd.h"
#import "ZYCountSubtractor.h"
#import "ZYCountMuli.h"
#import "ZYCountDivision.h"
#import "ZYCountTool.h"
#import "ZYAddTool.h"
@interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; ZYCountAdd *p = (ZYCountAdd *)[ZYAddTool createOperation];
p.numberA = 10;
p.numberB = 20;
NSLog(@"%lf",[p resultForCount]);
} @end

以这样的模式来设计运算操作的代码,可以清楚的得知,当需要增加一个m的n次方的运算时,只需要继承运算类增加一个子类,继承工具类增加一个子类,就可以轻松实现了,从而避免的简单工厂里面那种要去修改工具类的方法,也就符合了开放-封闭原则(ocp)。

仔细观察就会发现,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断转移到了viewController里面来进行,你想要增加功能,本来是修改工厂类的,而现在时修改viewController。

那么还是要修改viewController?尽管换成其他运算类,还是要修改,但是只需修改一处就可以了,比简单工厂方法好很多了。

工厂方法模式客服了简单工厂模式中违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。工厂方法是简单工厂模式的进一步抽象和推广,由于使用多态性,工厂模式保持了简单工厂模式的优点,而客服了它的缺点。但缺点就是每增加一个产品,就需要增加一个产品工厂类,增加了额外的开发量。(解决方案,后续有...)

设计模式之工厂方法模式(代码用Objective-C展示)的更多相关文章

  1. C#设计模式(3)——工厂方法模式

    一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...

  2. 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

    原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...

  3. C#设计模式(3)——工厂方法模式(转)

    C#设计模式(3)——工厂方法模式   一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过 ...

  4. php设计模式之工厂方法模式

    php设计模式之工厂方法模式 工厂方法模式 工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Pol ...

  5. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  6. Java设计模式之工厂方法模式(转) 实现是抽象工厂?

    Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织   2009-02-25   来源:IT168网站   文本Tag: 设计模式 Java [IT168 技术文章]         ...

  7. Java设计模式 之 工厂方法模式

    1. 使用设计模式的好处:可提高代码的重复性,让代码更容易被他人理解,保证代码的可靠性. 2. 工厂模式定义:就是创建一个工厂类来创建你需要的类,工厂模式包括工厂模式和抽象工厂模式,抽象工厂模式是工厂 ...

  8. Android设计模式系列--工厂方法模式

    工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式.android中用到了太多的工厂类,其中有用工厂方法模式的,当然也有很多工厂并不是使用工厂方法模式的,只是工具 ...

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

    1. 模式意图:  定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...

随机推荐

  1. IT软件外包行业深入分析:现状、前途、趋势、待遇 什么是软件外包 外包公司是怎么工作的 软件外包公司的面试 软件外包公司需要什么样的人

    目录: [0] - 为什么要对大学生谈软件外包? [1] - 什么是软件外包? [2] - 软件为什么要外包? [3] - 为什么要承接软件外包 [4] - 做软件外包有前途吗? [5] - 外包公司 ...

  2. 联想Thinkpad笔记本自带win10改win7图文教程

    一.准备工作: 1.备份转移硬盘所有文件 2.改装win7将删除所有分区,要恢复预装的win10系统需到售后 3.4G空间以上U盘,制作U盘PE启动盘 4.操作系统:联想Lenovo笔记本专用GHOS ...

  3. 收集一些常用Javascripot

    获取一组单选框当前选择值: $("input[name='radGende']:checked").val();

  4. 【Struts2】Struts2获取session的三种方式

    1.Map<String,Object> map =  ActionContext.getContext().getSession(); 2.HttpSession session = S ...

  5. java单双派机制理解

    引言:Java是一个支持双分派的单分派语言 知道java是支持后期动态绑定,也知道访问者模式,但是两者之间的关系,还真不知道,况且在这之间还有一个静态绑定. 1.动态绑定 class Father { ...

  6. 高效的MySQL分页——利用子查询分页

    ——先抄回来~~~ 首先看一下分页的基本原理: mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20G*** ...

  7. easyui按钮linkbutton 不可用(置灰)与 可用(取消置灰)

    easyui linkbutton按钮: 不可用(置灰) $('#butFree').linkbutton('disable'); 可用(取消置灰) $('#butFree').linkbutton( ...

  8. 【转】Lisp 已死,Lisp 万岁!

    Lisp 已死,Lisp 万岁! 有一句古话,叫做“国王已死,国王万岁!”它的意思是,老国王已经死去,国王的儿子现在继位.这句话的幽默,就在于这两个“国王”其实指的不是同一个人,而你咋一看还以为它自相 ...

  9. Android HttpURLConnection源代码分析

    Android HttpURLConnection源代码分析 之前写过HttpURLConnection与HttpClient的差别及选择.后来又分析了Volley的源代码. 近期又遇到了问题,想在V ...

  10. Gitlab Runner的使用(涵盖gitlab-page)

    #gitlab-runner 的简单安装和部署##背景 因为公司要使用CI 功能,已经使用gitlab-page的功能能,所以这里记录一下 ###安装步骤:    参考官方文档:https://doc ...