定义

策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

模式结构

策略模式包含如下角色:

  • Context: 环境类
  • Strategy: 抽象策略类
  • ConcreteStrategy: 具体策略类

策略模式 - 图1

适用场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
  • 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。

    代码分析

    理财产品的回报计算,处理方式是一样的,客户端只要给固定的参数(平台、月份、金额),需要计算出本金及利息的和,不同理财产品的计算接口定义是统一的,在实现上有差别,所以类似这种场景是比较适合使用策略模式的。

    定义策略接口

    这个案例中策略接口是理财产品计算算法的接口 ```objectivec

    import

    @protocol FinancyStrategyProtocal
  • (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money; @end ```

    定义Context类

    Context类使用到了算法对象,这个对象是可以相互替换的 ```objectivec // FinancyContext.h

    import

    import “FinancyStrategyProtocal.h”

    @interface FinancyContext : NSObject

@property (nonatomic, strong) id financy;

  • (instancetype)initWithFinancy:(id)financy;
  • (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money; @end // FinancyContext.m

    import “FinancyContext.h”

    @implementation FinancyContext
  • (instancetype)initWithFinancy:(id)financy { self = [super init]; if (self) {
    1. _financy = financy;
    } return self; }
  • (NSInteger)financyWithMonth:(NSInteger)month money:(NSInteger)money { return [_financy financyWithMonth:month money:money]; } @end ```

    策略A类的具体实现

    ```objectivec // YouLiFinancyStrategy.h

    import

    import “FinancyStrategyProtocal.h”

    @interface YouLiFinancyStrategy : NSObject @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) {

    1. return money * 0.03f / 12 * month + money;

    } else if (month <= 12) {

    1. return money * 0.04f / 12 * month + money;

    } else if (month <= 24) {

    1. return money * 0.045f / 12 * month + money;

    }

    return 0; } @end ```

    策略B类的具体实现

    ```objectivec // AlipayFinancyStrategy.h

    import

    import “FinancyStrategyProtocal.h”

    @interface AlipayFinancyStrategy : NSObject @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) {

    1. return money * 0.07f / 12 * month + money;

    } else if (month <= 6) {

    1. return money * 0.08f / 12 * month + money;

    } else if (month <= 12) {

    1. return money * 0.095f / 12 * month + money;

    } else if (month <= 24) {

    1. return money * 0.105f / 12 * month + money;

    } return 0; } @end 客户端使用objectivec id alipayFinancy = [[AlipayFinancyStrategy alloc] init]; FinancyContext* context = [[FinancyContext alloc] initWithFinancy:alipayFinancy]; NSInteger money = [context financyWithMonth:6 money:10000]; NSLog(@”Alipay money = %@”, @(money));

id ylFinancy = [[YouLiFinancyStrategy alloc] init]; context.financy = ylFinancy; money = [context financyWithMonth:6 money:10000]; NSLog(@”YouLi money = %@”, @(money)); ```

优点

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法。
  • 策略模式提供了可以替换继承关系的办法。
  • 使用策略模式可以避免使用多重条件转移语句。

    缺点

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。