包含角色
- 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()方法可以动态替换策略的实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。