为什么要替代if/else
开发过程中避免不了使用if/else进行逻辑判断,如果逻辑很复杂、判断逻辑会频繁改动或者后期会增加判断逻辑,那么if/else会导致代码很难理解且难以维护,建议大家采用策略模式来代替if/else
策略模式
将非固定功能抽取出来,独立定义接口和实现类,在Manager类中聚合,实现组装类的效果,达到以下效果:
- 可读性,编程规范性,便于其他程序员阅读和理解
- 可扩展性,可维护性,需要添加新功能时,非常方便,成本低
- 可靠性,添加新功能或减少功能后,对原有功能没有影响
- 满足开闭原则
示例
假设有这样的一个需求,根据员工上个月迟到和加班次数来计算奖金,如果迟到>=3次就每次扣100元,如果加班>5次就每次加50元,这个需求不管是否合理,只是一种假设。
先定义一个对象来记录迟到和加班的次数
StaffData staffData = StaffData.builder()
.chidao(3)
.jiaban(10)
.build();
复制代码
使用if/else的代码如下:
public static int calc(StaffData staffData) {
int total = 0;
if (staffData.getChidao() != null && staffData.getChidao() >= 3) {
total -= staffData.getChidao() * 100;
}
if (staffData.getJiaban() != null && staffData.getJiaban() > 5) {
total += staffData.getJiaban() * 50;
}
return total;
}
System.out.println("奖金=" + calc(staffData));
复制代码
如果后期增加了需求,在StaffData中添加请假次数,请假超过3次则每次扣100元的规则,那么需要继续在calc方法中添加if
如果又要新增一个规则,在StaffData中添加迟到次数和基本工资,请假超过5次,迟到超过5次,直接扣基本工资的一半,仍然需要在calc方法中添加代码,最后calc方法会越来越复杂,日积月累之后很难再去维护,修改不当还会导致原先的逻辑发生错误
采用策略模式
先定义一个Policy
接口,通常定义canApply
方法来进行逻辑判断,定义apply
方法执行相应的业务逻辑
public interface Policy {
/**
* 当前策略是否匹配
*
* @param data
* @return
*/
boolean canApply(StaffData data);
/**
* 执行策略
*
* @param data
* @return
*/
int apply(StaffData data);
}
复制代码
定义一个策略管理类,这个类负责注入所有策略,然后对外提供一个apply
方法,遍历调用所有的策略,并做相应的处理,简化外部调用
@Component
public class PolicyManager {
@Autowired
private List<Policy> policies;
public int apply(StaffData data) {
int total = 0;
for (Policy policy : policies) {
if (policy.canApply(data)) {
total += policy.apply(data);
}
}
return total;
}
}
复制代码
接下来可以定义需要的策略了
/**
* 规则如果迟到>=3次就匹配
*/
@Component
public class Test1Policy implements Policy {
@Override
public boolean canApply(StaffData data) {
return data.getChidao() != null && data.getChidao() >= 3;
}
@Override
public int apply(StaffData data) {
// 迟到1次扣100
return -data.getChidao() * 100;
}
}
复制代码
再定义一个策略
/**
* 如果加班超过5次就匹配
*/
@Component
public class Test2Policy implements Policy {
@Override
public boolean canApply(StaffData data) {
return data.getJiaban() != null && data.getJiaban() > 5;
}
@Override
public int apply(StaffData data) {
// 加班1次加50
return data.getJiaban() * 50;
}
}
复制代码
最后测试一下逻辑是否正确
@SpringBootApplication
public class PolicyTest {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(PolicyTest.class, args);
PolicyManager manager = context.getBean(PolicyManager.class);
StaffData staffData = StaffData.builder()
.chidao(3)
.jiaban(10)
.build();
System.out.println("奖金=" + manager.apply(staffData));
}
}
复制代码
后期添加计算规则时新增一个策略类就可以实现,不用去修改原先写好的策略类,代码也很清晰,各个策略类只负责自己要处理的业务
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END