戳我
戳我
文章目录
  1. 设计模式-工厂模式
    1. 版本一
    2. 版本二
    3. 版本三

设计模式-工厂模式

设计模式-工厂模式

下面有一个case, 要编写一个简单的计算器程序, 用来实现加减乘除的运算操作, 并且展示出来.我们就拿这个最简单的例子来一步一步见识一下”工厂模式”的魅力.

版本一

版本一:我们首先想到的最简单的模式就是我们先从业务上来拆分, 把计算器程序分成两部分计算展示两个类来写代码.OC作为一门面向对象的语言, 在这里我们已经可以清楚地意识到我们已经使用了封装这面向对象语言的一大特性.但是随着业务的发展, 我们发现可能会增加其他的业务(例如增加其他的运算操作),这是我们每次都要修改计算这个类, 慢慢的代码就会越来越多, 不利于维护.而且在新加逻辑的过程中有可能会修改到老的代码, 维护成本很高.这是我们就会想到其他两个特性继承多态.于是, 就有了版本二.

版本二

这时我们发现,把所有的运算写到一个类中是有些不妥当的, 那么要怎么来修改呢.我们自然地想到, 每一种运算可以单独度的封装为一个类, 只用于实现固定的计算.于是我们可以得到,,,四个类, 每个类都三个属性, 分别是操作数结果.哪里怪怪的呢, 有没有一丝”坏代码”的味道呢.通过提炼我们发现四个类都有相同的三个属性,那么我们可以这样做新建一个Operation操作类, 包含三个Public属性

@interface Operation : NSObject

@property (nonatomic, assign) CGFloat numberA;
@property (nonatomic, assign) CGFloat numberB;
@property (nonatomic, assign) CGFloat numberResult;

- (CGFloat)getResult;
@end

这样的话, 只需要每一个单独的计算类继承于Operation类, 就会自带父类的三个属性, 只用在他们内部实现自己独有的计算方法, 返回计算结果就可以了.到这里, 我们会发现代码变得更加有意思了.
但是我们又发现了一个新的问题, 那就是我们该何时初始化哪个类呢, 毕竟我们现在有了四个计算子类.我们只好计算结果的地方写Switch条件来判断到底要初始化那一个子类.

可是仍然感觉哪里还是怪怪的.我们不是还有多态这种特性没有使用的嘛.仔细一想, 于是又有了版本三.

版本三

多态:多态表示不同的对象可以执行相同的操作, 但要通过他们自己的实现代码来执行.
这是我们需要增加一个工厂类OperationFactory, 用来判断要初始化哪一个子类.

OperationFactory.h代码如下:

@class Operation;
@interface OperationFactory : NSObject

+ (Operation *)createOperationWithOperate:(NSString *)operate;
@end

OperationFactory.m代码如下:

@implementation OperationFactory

//传入计算符号, 初始化不同的子类
+ (Operation *)createOperationWithOperate:(NSString *)operate {
    if ([operate isEqualToString:@"+"]) {
        OperationAdd *add = [[OperationAdd alloc] init];
        return add;
    }

    if ([operate isEqualToString:@"-"]) {
        OperationSubtraction *subtraction = [[OperationSubtraction alloc] init];
        return subtraction;
    }

    ...
    return nil;
}

@end

此时展示的地方, 代码就变得很简单了:

@interface ViewController ()

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    Operation *operation = [OperationFactory createOperationWithOperate:@"-"];//子类以父类的身份出现
    operation.numberA = 3;
    operation.numberB = 5;
    CGFloat result = [operation getResult];//子类在工作时以自己的方式实现
    NSLog(@"%f", result);
    NSLog(@"%f", operation.numberResult);
}
@end

如上我们可以发现, 整个工厂模式的关键就在于OperationFactory这个工厂类的实现.我们在调用的时候不用关心我们要实现哪一个类, CGFloat result = [operation getResult];, 只用调用父类的方法就可以, 而内部则是子类自己的实现.
这里面还有几点要注意:

  1. 子类以父类的身份出现
  2. 子类在工作时以自己的方式实现
  3. 子类独有的方法和属性不可以使用

在这里解释一下就是, 我们在展示的时候初始化的实际上是父类Operation.但是在获取计算结果时, 我们使用的是子类的计算方法CGFloat result = [operation getResult];, 因为我们在子类里面复写了父类的方法, 所以实际上走的还是子类各自自己的方法.