1、简述

首先需要说明一下,简单工厂模式不属于23种GOF设计模式之一。它也称作静态工作方法模式,是工厂方法模式的特殊实现(也就是说工厂模式包含简单工厂模式)。这里对简单工厂模式进行介绍,是为后面的工厂方法和抽象工厂模式做一个引子。

2、定义

“专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类。”

世界上就是由一个工厂类,根据传入的参数,动态地决定创建出哪一个产品类的实例。

3、结构图

简要分析结构图:

ConcreteProduct1和ConcreteProduct2两个产品具有一个共同的父类IProject,简单工厂类为SimpleFactory,负责根据传入的不同参数来决定生产ConcreteProduct1还是ConcreteProduct2产品。

4、代码示例讲解

模拟一个使用计算器的场景:用户可以输入两个数和操作符号,然后得到结果,使用交互如下图所示,分别进行除运算和减运算,

(1)除运算示例

(2)减运算示例

一个新手,极有可能按照自己的初步思维逻辑,判断用户输入的运算符,然后将两个数字进行运算,当然还会加上必要的除数不为0的判断,那么点击运算Button,对应的事件可以如下面这样编写,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- (IBAction)getResult:(id)sender {
    //得到三个文本输入框的内容
    NSString* strFirstNum = self.FirstNumTextField.text;
    NSString* strSecondNum = self.SecondNumTextField.text;
    NSString* strOperation = self.OperationTextField.text;
    //进行运算操作
    if ([strOperation isEqualToString:@"+"]) {
        NSLog(@"+");
        double result = [strFirstNum doubleValue]+[strSecondNum doubleValue];
        self.ResultTextField.text = [NSString stringWithFormat:@"%f",result];
    }else if([strOperation isEqualToString:@"-"]){
        NSLog(@"-");
        double result = [strFirstNum doubleValue]-[strSecondNum doubleValue];
        self.ResultTextField.text = [NSString stringWithFormat:@"%f",result];
    }else if([strOperation isEqualToString:@"*"]){
        NSLog(@"*");
        double result = [strFirstNum doubleValue]*[strSecondNum doubleValue];
        self.ResultTextField.text = [NSString stringWithFormat:@"%f",result];
    }
    else if([strOperation isEqualToString:@"/"]){
        NSLog(@"/");
        //判断除数不能为0
        if ([strSecondNum isEqualToString:@"0"]) {
            NSLog(@"除数不能为0");
            UIAlertView* tempAlert = [[UIAlertView alloc] initWithTitle:@"警告" message:@"除数不能为0" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
            [tempAlert show];
        }else{
            double result = [strFirstNum doubleValue]/[strSecondNum doubleValue];
            self.ResultTextField.text = [NSString stringWithFormat:@"%f",result];
        }
    }
}

恩,这样写肯定能够实现功能。但是如果进行更多的运算,例如增加开平方、乘方运算,增加100种运算,那么是不是要增加100个else if判断语句呢?如果这样去做每次都要去修改这部分代码,这样有悖于可扩展性原则。所以我们需要引入简单工厂模式,把运算给抽象出来,并且加入运算工厂用于接收用户的操作。

注释:这里我们把运算这个动作给抽象出来,当做一个对象,可能很多人觉得有点迷糊。我们知道,面向对象编程是不同于面向过程编程的,通常将一个事物给抽象成一个类,类具有属性和方法;那么我们也可以把一个动作进行抽象,例如此处的运算Operation,它具有两个属性(前一个操作数和后一个操作数),它具有的方法就是获取运算的结果。所以深入理解面向对象编程,还有很多的路要走。

那么此处我们可以抽象出一个UML图,如下所示,

与上面的UML结构图类似,这里再简单解释一下,加、减、乘、除四个运算符都继承自父类Operation,有两个属性和一个操作方法,这些加减乘除的对象并不是直接在ViewController中创建,而是根据输入操作符,由简单工厂OperationFactory来创建。

(1)创建一个协议OprationProtocol,由父类Operation来遵从该协议

1
2
3
4
5
6
/*
 *  操作方法协议接口
 */
@protocol OperationProtocol <NSObject>
-(double)getResult;
@end

(2)定义加减乘除操作的父类Operation

1
2
3
4
5
6
7
8
#import OperationProtocol.h
/*
 *  操作方法父类
 */
@interface Operation : NSObject<operationprotocol>
@property double firstNum;//第一个操作数
@property double secondNum;//第二个操作数 
@end

(3)加减乘除实现类,此处以"加"举例说明,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//OperationAdd.h文件
#import Operation.h
/*
 *  加法实现类
 */
@interface OperationAdd : Operation
@end
 
//OperationAdd.m文件
#import "OperationAdd.h"
@implementation OperationAdd
-(double)getResult
{
    double result = 0;
    result = self.firstNum+self.secondNum;//"+"是OperationAdd时候使用,"+-*/"分别对应"加减乘除"
    return result;
}
@end

(4)简单工厂类的代码,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//OpeartionFactory.h file
#import Operation.h
#import OperationAdd.h
#import OperationSub.h
#import OperationMultiply.h
#import OperationDivide.h
/*
 *  操作工厂类
 */
@interface OperationFactory : NSObject
  
//获得操作对象
+(Operation*)createOperate:(NSString*)operateStr;
  
@end
 
//OpeartionFactory.m file
#import "OperationFactory.h"
@implementation OperationFactory
 
+(Operation*)createOperate:(NSString*)operateStr
{
    Operation* oper = nil;
    //根据不同的操作符,创建不同的操作对象,"+-*/"分别对应"加减乘除"
    if ([operateStr isEqualToString:@"+"]) {
        oper = [[OperationAdd alloc] init];
    }else if ([operateStr isEqualToString:@"-"]){
        oper = [[OperationSub alloc] init];
    }else if ([operateStr isEqualToString:@"*"]){
        oper = [[OperationMultiply alloc] init];
    }else if ([operateStr isEqualToString:@"/"]){
        oper = [[OperationDivide alloc] init];
    }
    return oper;
}
@end

(5)客户端代码,在ViewController中使用OperationFactory

1
2
3
4
5
6
7
8
9
- (IBAction)clickingOperation:(id)sender {
    NSString* strFirstNum = self.firstNumTextField.text;
    NSString* strSecondNum = self.secondNumTextField.text;
    Operation* oper;
    oper = [OperationFactory createOperate:self.operationTextField.text];
    oper.firstNum = [strFirstNum doubleValue];
    oper.secondNum = [strSecondNum doubleValue];
    self.resultTextField.text = [NSString stringWithFormat:@%f,[oper getResult]];
}

这样的话ViewController中的代码看起来就简洁明了,而且易于扩展。

那么我们根据ViewController中的代码,分析一下使用思路,把操作类类比成一个容器,它有输入端(操作符号、第一个操作数、第二个操作数)和输出端(运算结果),如下图所示,

所以上面的代码将ViewController的TextField中的输入内容拿过来创建操作对象,并且把操作运算的逻辑放在了Operation及其子类中实现,然后将结果返回给ViewController,这样减少了ViewController的逻辑代码。

通过简单工厂模式的重构,我们就是闲了低耦合度的代码结构,做到了对外扩展开放,对修改关闭。如果再增加任何的操作方法,只需要继承操作方法父类,新建一个操作子类,并且在简单工厂类里面多添加一个else if的判断即可。

五、优缺点

优点:简单工厂模式的优点是客户端可以直接消费产品,而不必关心具体产品的实现,消除了客户端直接创建产品对象的责任,实现了对责任的分割。

缺点是工厂类几种了所有产品的创建逻辑,一旦不能正常工作,整个系统都会受到影响,而且当产品类多结构复杂的时候,把所有创建工作放进一个工厂中来,回事后期程序的扩展较为困难。

通过优缺点的分析,我们可以再如下场景中使用简单工厂模式:

(1)工厂类负责创建的对象较少时;

(2)客户端只知道传入工厂类的参数,对于如何创建对象的逻辑不必关心时。

iOS设计模式:简单工厂模式的更多相关文章

  1. iOS 设计模式之工厂模式

    iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...

  2. 3. 星际争霸之php设计模式--简单工厂模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  3. Golang设计模式—简单工厂模式(Simple Factory Pattern)

    Golang设计模式--简单工厂模式 背景 假设我们在做一款小型翻译软件,软件可以将德语.英语.日语都翻译成目标中文,并显示在前端. 思路 我们会有三个具体的语言翻译结构体,或许以后还有更多,但现在分 ...

  4. iOS开发-简单工厂模式

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.概念很长,iOS开发中最常 ...

  5. C++设计模式——简单工厂模式

    简单工厂模式(Simple Factory Pattern) 介绍:简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些.因为它至少不是Gof23种设计模式之一.但它在实际的编程中经常被用 ...

  6. 深入浅出设计模式——简单工厂模式(Simple Factory)

    介绍简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些.因为它至少不是Gof23种设计模式之一.但它在实际的编程中经常被用到,而且思想也非常简单,可以说是工厂方法模式的一个引导,所以我想 ...

  7. C#设计模式--简单工厂模式

    简单工厂模式是属于创建型模式,但不属于23种GOF设计模式之一. 举一个例子:一个公司有不同的部门,客户根据需要打电话到不同的部门.客户相当于上端,不同部门相当于下端.不使用简单工厂模式来实现的例子如 ...

  8. 设计模式 | 简单工厂模式(static factory method)

    按理说应该把书全都看完一遍,再开始写博客比较科学,会有比较全面的认识. 但是既然都决定要按规律更新博客了,只能看完一个设计模式写一篇了. 也算是逼自己思考了,不是看完就过,至少得把代码自己都敲一遍. ...

  9. Yii2设计模式——简单工厂模式

    除了使用 new 操作符之外,还有更多的制造对象的方法.你将了解到实例化这个活动不应该总是公开进行,也会认识到初始化经常造成"耦合"问题. 应用举例 yii\db\mysql\Sc ...

  10. 设计模式 — 简单工厂模式(staticFactory)

    这篇博文介绍简单工厂模式,设计模式并不是固定的二十三种,不同的书介绍的可能有出入,这篇介绍的简单工厂模式在有些书上就忽略不介绍了.设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验 ...

随机推荐

  1. JAVA常见算法题(三十二)---找规律

    题目一: 4,5,15,45,135,405,__ 题目二: 524,244,954,674,394,15,725, __ 题目三: 7,8,6,9,10,7,4,4,5,__ 求横线位置的整数. * ...

  2. 郑捷2017年电子工业出版社出版的图书《NLP汉语自然语言处理原理与实践》

    郑捷2017年电子工业出版社出版的图书<NLP汉语自然语言处理原理与实践> 第1章 中文语言的机器处理 1 1.1 历史回顾 2 1.1.1 从科幻到现实 2 1.1.2 早期的探索 3 ...

  3. Objective-C:NSMutableArray类的常见操作

    可变数组NSMutableArray的内容大小是可变的,因此它的常见操作无非增删该查, 具体一些就是:创建.添加.删除.替换.插入.清空等等.. // //  main.m //  02-NSMuta ...

  4. 3D几何图形的生成算法

    在之前的博客上,发布了一个我写的3D几何图形生成的DEMO: http://www.cnblogs.com/WhyEngine/p/3415040.html DEMO下载地址: http://file ...

  5. Informatica 常用组件Lookup缓存之五 使用动态查找高速缓存

    对于关系查找,当目标表也是查找表时,可能要配置转换以使用动态高速缓存.PowerCenter 将在处理第一个查找请求时创建高速缓存.它将根据查找条件为传递给转换的每行查询高速缓存.当您使用动态高速缓存 ...

  6. go语言基础之结构体比较和赋值

    1.结构体比较和赋值 (同类型的结构体可以相互赋值) 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Stud ...

  7. Android中XML解析-Dom解析

    Android中需要解析服务器端传过来的数据,由于XML是与平台无关的特性,被广泛运用于数据通信中,有的时候需要解析xml数据,格式有三种方式,分别是DOM.SAX以及PULL三种方式,本文就简单以D ...

  8. jQuery用面向对象的思想来编写验证表单的插件

    本人的重点是怎么构建一个简单有效可扩展的jQuery表单验证插件,这篇文章没有教你怎么用 validate plugin.我们的重点在学习一些jQuery,Javascript面向对象编程的知识. 下 ...

  9. Vue路由scrollBehavior滚动行为控制锚点

    使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样. vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动. 注意: 这个功能只 ...

  10. ListView 设置列对齐方式

    <ListView.Resources> <Style TargetType="ListViewItem"> <Setter Property=&qu ...