iOS模式分析 策略模式

aron1992發表於2019-04-04

好久了,過去了一個月沒有動筆寫東西了,除了工作的忙,還有最近在學習一個課程和看一些技術類的書籍,騰不出時間來寫部落格了,說了這麼多,其實歸根結底都是我懶的藉口,確實挺慚愧,還是得繼續加油,多寫多練習,做更好的自己。。。

策略模式

本文使用OC語言實現策略模式的實現

定義

定義一系列可以相互替換的演算法類,提供給客戶端相同的呼叫介面,客戶端呼叫不同的物件的相同方法來達到快速切換演算法的目的。

使用場景

下面是從程式設計原則討論策略模式的使用場景

  • 針對同一個問題的多種不同的處理方式,但是具體的實現有差異,需要實現統一的介面,對變化部分進行封裝【面向抽象而非面向具體原則】。
  • 分支太多導致了客戶端對演算法實現類的依賴太大,演算法擴充套件需要去修改實現--新增對應的分支,使得擴充套件不方便以及演算法類中的程式碼量膨脹。為了讓演算法類的擴充套件容易,需要對具體的演算法獨立封裝【開閉原則】;為了讓演算法程式碼保持最小和最簡單,需要對具體的演算法獨立實現【單一職責原則】。

案例實現

理財產品的回報計算,處理方式是一樣的,客戶端只要給固定的引數(平臺、月份、金額),需要計算出本金及利息的和,不同理財產品的計算介面定義是統一的,在實現上有差別,所以類似這種場景是比較適合使用策略模式的。

不同產品的利率:
有利網:
​短期理財:6個月以內,年化收益:3%
​​​中期理財:12個月以內,年化收益:4%
​​​長期理財:24個月以內,年化收益:4.5%
支付寶:
​定期理財3個月,年化收益:7%
​​​定期理財6個月,年化收益:8%
​​​定期理財12個月,年化收益:9.5%
​​​定期理財24個月,年化收益:10.5% :10.5%

下面是理財產品這個案例的具體模組的程式碼實現。

定義策略介面

這個案例中策略介面是理財產品計算演算法的介面

#import <Foundation/Foundation.h>

@protocol FinancyStrategyProtocal <NSObject>

- (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money;

@end
複製程式碼

定義Context類

Context類使用到了演算法物件,這個物件是可以相互替換的

// FinancyContext.h
#import <Foundation/Foundation.h>
#import "FinancyStrategyProtocal.h"

@interface FinancyContext : NSObject

@property (nonatomic, strong) id<FinancyStrategyProtocal> financy;
- (instancetype)initWithFinancy:(id<FinancyStrategyProtocal>)financy;
- (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money;
@end


// FinancyContext.m
#import "FinancyContext.h"

@implementation FinancyContext

- (instancetype)initWithFinancy:(id<FinancyStrategyProtocal>)financy {
    self = [super init];
    if (self) {
        _financy = financy;
    }
    return self;
}

- (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money {
    return [_financy financyWithMonth:month money:money];
}
@end
複製程式碼

策略類的具體實現

A. 有利網的演算法策略實現

// YouLiFinancyStrategy.h
#import <Foundation/Foundation.h>
#import "FinancyStrategyProtocal.h"
@interface YouLiFinancyStrategy : NSObject <FinancyStrategyProtocal>
@end


// YouLiFinancyStrategy.m
#import "YouLiFinancyStrategy.h"

@implementation YouLiFinancyStrategy

- (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money {
//    短期理財:6個月以內,年化收益:3%
//    ​​​中期理財:12個月以內,年化收益:4%
//    ​​​長期理財:24個月以內,年化收益:4.5%
    
    if (month <= 6) {
        return money * 0.03f / 12 * month + money;
    } else if (month <= 12) {
        return money * 0.04f / 12 * month + money;
    } else if (month <= 24) {
        return money * 0.045f / 12 * month + money;
    }
    
    return 0;
}
@end
複製程式碼

A. 餘額寶的演算法策略實現

// AlipayFinancyStrategy.h
#import <Foundation/Foundation.h>
#import "FinancyStrategyProtocal.h"
@interface AlipayFinancyStrategy : NSObject <FinancyStrategyProtocal>
@end


// AlipayFinancyStrategy.m
#import "AlipayFinancyStrategy.h"

@implementation AlipayFinancyStrategy 

- (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money {
//    ​定期理財3個月,年化收益:7%
//    ​​​定期理財6個月,年化收益:8%
//    ​​​定期理財12個月,年化收益:9.5%
//    ​​​定期理財24個月,年化收益:10.5%
    
    if (month <= 3) {
        return money * 0.07f / 12 * month + money;
    } else if (month <= 6) {
        return money * 0.08f / 12 * month + money;
    } else if (month <= 12) {
        return money * 0.095f / 12 * month + money;
    } else if (month <= 24) {
        return money * 0.105f / 12 * month + money;
    }
    return 0;
}
@end
複製程式碼

客戶端使用

    id<FinancyStrategyProtocal> alipayFinancy = [[AlipayFinancyStrategy alloc] init];
    FinancyContext* context = [[FinancyContext alloc] initWithFinancy:alipayFinancy];
    NSInteger money = [context financyWithMonth:6 money:10000];
    NSLog(@"Alipay money = %@", @(money));
    
    id<FinancyStrategyProtocal> ylFinancy = [[YouLiFinancyStrategy alloc] init];
    context.financy = ylFinancy;
    money = [context financyWithMonth:6 money:10000];
    NSLog(@"YouLi money = %@", @(money));
複製程式碼

UML分析

strategy-pattern-diagram
strategy-pattern-diagram

Demo

StrategyPatternDemo

相關文章