首页 技术 正文
技术 2022年11月7日
0 收藏 607 点赞 956 浏览 5180 个字

1、简述

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

2、定义

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

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

3、结构图

iOS设计模式:简单工厂模式

简要分析结构图:

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

4、代码示例讲解

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

(1)除运算示例

iOS设计模式:简单工厂模式

(2)减运算示例

iOS设计模式:简单工厂模式

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

?

1234567891011121314151617181920212223242526272829303132 - (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图,如下所示,

iOS设计模式:简单工厂模式

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

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

?

123456 /* *  操作方法协议接口 */@protocol OperationProtocol <NSObject>-(double)getResult;@end

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

?

12345678 #import OperationProtocol.h/* *  操作方法父类 */@interface Operation : NSObject<operationprotocol>@property double firstNum;//第一个操作数@property double secondNum;//第二个操作数 @end

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

?

123456789101112131415161718 //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)简单工厂类的代码,

?

123456789101112131415161718192021222324252627282930313233343536 //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

?

123456789 - (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中的代码,分析一下使用思路,把操作类类比成一个容器,它有输入端(操作符号、第一个操作数、第二个操作数)和输出端(运算结果),如下图所示,

iOS设计模式:简单工厂模式

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

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

五、优缺点

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

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

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

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

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

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,085
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,560
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,409
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,182
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,819
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,902