zoukankan      html  css  js  c++  java
  • 设计模式之工厂方法模式(代码用Objective-C展示)

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

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

    加减乘除运算都是继承自基类运算类,然后工厂类来调用这些运算,创建相应的对象,从而进行操作,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?尽管换成其他运算类,还是要修改,但是只需修改一处就可以了,比简单工厂方法好很多了。

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

     

  • 相关阅读:
    航班延误来领钱,信用卡航班延误险最全攻略(2018年版)
    各银行信用卡延误险整理
    酒店web认证802.11x+ROS共享NAT上网
    登机牌,机票,行程单的区别
    ros6.0的包转发图解
    一将成,万骨枯,趣店上市背后的残酷游戏
    异常值检验实战1--风控贷款年龄变量(附python代码)
    outlier异常值检验算法之_箱型图(附python代码)
    sklearn11_函数汇总
    python高级数据可视化Dash2
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/4826464.html
Copyright © 2011-2022 走看看