乐趣区

关于设计模式:一天一个设计模式策略模式

蕴含角色

  • context 策略使用者
  • strategy 策略 (行为) 接口
  • strategyImpl 策略的具体实现,通常这些实现也叫算法族

场景案例

demo1- 佣金核算

假如当初有三种业绩类型 (A,B,C) 须要核算佣金, 通过业务剖析, 三种核算过程都蕴含以下步骤:

  • 查问元数据
  • 清空重置上一次佣金计算
  • 核算佣金
  • 判断佣金归属

个别的做法是定义一个核算接口, 接口中定义上述办法, 而后实现核算接口, 在不同的接口实现类中实现相应的细节

// 核算接口
public interface ICalculate{query();
    clear();
    calculate();
    belong();}

// A 类型业绩核算
public class ACalculate implements ICalculate{
    // A 类型具体实现
    query();
    clear();
    calculate();
    belong();}

// B 类型业绩核算
public class BCalculate implements ICalculate{
    // B 类型具体实现
    query();
    clear();
    calculate();
    belong();}
 // 其余类型...

上述写法中, 存在一些问题:

  • 如果 C 类型中没有 clear 清空逻辑呢?
  • 能够在 C 类中不去实现 clear()办法
  • 如果前期业务变更, 不须要 belong()办法了呢. 新增的类型能够不做具体实现, 已有的类型呢? 须要一一删除 belong()办法
  • 如果前期新增了逻辑呢? 如: 核算团队业绩, 计算指标完成率
  • 须要大量改变已实现的代码
  • 因为政策变动,A,B,C 采纳全新对立的 query 查问,clear 清空逻辑, 核算和归属逻辑不同
  • 最后各种类型的业绩核算, 查问清空等逻辑不同, 所以实现细节全副放在了核算类中, 现在许多办法能够共用, 就从新定义接口, 并实现 query/clear 新的逻辑, 而后在业绩核算类中注入

这些是工作中实在遇到的状况, 问题不言而喻:

  • 耦合度高: 算法的实现与算法使用者耦合
  • 代码复用低: 如果不同核算类型中用到雷同逻辑, 只能复制粘贴
  • 拓展性太差: 在核算过程中新增和删除某个环节, 会批改大量代码
  • 代码不足设计, 档次凌乱.

思考:

  • 是否将核算过程中用到的核算环节与核算类分来到?
  • 如果办法能够共用, 在核算类中能够间接注入接口实现
  • 即便不能共用, 批改或新增核算环节时不须要改变核算类, 代码档次更清晰了
  • 是否将这些办法形象成接口?
  • 依据核算类型的业务需要, 这些办法能够有不同的实现
  • 核算的环节将不再固定, 能够是任意步骤. 新增核算环节只须要定义新的行为接口
// 应用策略模式优化
// 1. 将核算环节形象为行为接口, 即核算过程有哪些行为
// 2. 行为接口能够有不同的具体实现, 这些实现类能够看成是一个算法族
// 3. 通过组合的形式, 使核算过程变动多样

// 查问策略
public interface Query{query();
}
// 查问策略算法族
public class TypeAQuery{query(){//typeA logic}
}
public class TypeBQuery{query(){//typeB logic}
}

// 清空策略
public interface Clear{clear();
}

 '其余策略(行为) ...'

// 业绩类型 A 的核算
public class ACalculate {
    // 自定义核算环节, 自定义核算环节具体实现
    private Query query;
}

// 业绩类型 B 的核算
public class BCalculate {
    // 自定义核算环节
    private Query query;
    private Clear clear;
}

// 调用过程中, 通过 set()办法能够动静替换策略的实现
退出移动版