场景假设
当前界面是一个工资计算器,不同的角色有不同的计算逻辑,比如有三种角色:老师、院长、校长。在这个界面上可以选择角色、输入请假天数、输入工龄,自动计算出本月工资。
通常写法
class SalaryCalculator
public static final int ROLE_TEACHER = 1;
public static final int ROLE_DEAN = 2;
public static final int ROLE_PRESIDENT = 3;
private int role;
private int leaveCount;//请假天数
private int workYear;
private int salary;
private int baseSalary;
//...
if(role== ROLE_TEACHER) {
baseSalary = workYear*100+10000; //1年工龄月薪+100
} else if(role== ROLE_DEAN) {
if(workYear >= 10) {
baseSalary = workYear*300+20000;
} else {
baseSalary = workYear*200+20000;
}
} else {
baseSalary = workYear*500+30000;
}
//...为什么不把上下2个if else里面的代码合并起来,因为这只是DEMO,简单化了真实场景,真实场景比如这2段代码都需要各自在不同的回调里处理呢
if(role== ROLE_TEACHER) {
salary = baseSalary/23*(23 - leaveCount);
} else if(role== ROLE_DEAN) {
leaveCount = Math.max(leaveCount - 2, 0); //院长每个月有额外的2天假期
salary = baseSalary/23*(23 - leaveCount);
} else {
// 校长请假有半薪,且每个月有额外的3天假期
leaveCount = Math.max(leaveCount - 3, 0);
salary = baseSalary/23*(23-leaveCount)+ baseSalary/23/2*leaveCount;
}
//...
策略模式
class SalaryCalculator
public static final int ROLE_TEACHER = 1;
public static final int ROLE_DEAN = 2;
public static final int ROLE_PRESIDENT = 3;
private int role;
private int leaveCount;//请假天数
private int salary;
private SalaryStrategy strategy;
//...
if(role== ROLE_TEACHER) {
strategy = new TeacherSalaryStrategy ();
} else if(role== ROLE_DEAN) {
strategy = new DeanSalaryStrategy ();
} else {
strategy = new PresidentSalaryStrategy ();
}
//..
strategy.setWorkYear(workYear);
//...
strategy.setLeaveCount(leaveCount);
salary = strategy.getSalary();
//...
interface SalaryStrategy
private void setWorkYear();
private void setLeaveCount();
private int getSalary();
这个可以用接口,当然也可以用抽象类,抽象类里面还能封装一些基本的公共的代码。
class TeacherSalaryStrategy implements SalaryStrategy
private int baseSalary=10000;
private int salary;
private void setWorkYear(int workYear){
baseSalary = workYear*100+salary;
}
private void setLeaveCount(int leaveCount){
salary = baseSalary/23*(23 - leaveCount);
}
private int getSalary(){
if(salary==0){
salary = baseSalary;
}
return salary;
}
另外2个类,院长和校长的,自己想吧。
总结:
使用了策略模式后,SalaryCalculator类里面只会出现一次if else
的角色判断,明显简洁了很多。这样后续有对薪资算法的修改,就不用改SalaryCalculator类了,有针对性的去不同角色的策略类里面修改就可以了。
当你看到一个类里面出现多次相同的判断条件,如例子中出现2次
if(role== ROLE_TEACHER) {
} else if(role==ROLE_DEAN) {
} else {
}
(虽然DEMO只有2次,但是可以继续假设场景,写出N次if else)
就要考虑是否能把代码合并在同一个if else里,是否要使用策略模式。