代码整洁之道-第2章函数-switch语句优化

写出短小的switch语句很难,写出只做一件事的switch语句也很难,它天生就要做N件事。我们无法避开switch语句,不过还是可以确保每个switch都放在较低的抽象层级,而且永远不重复。

利用多态实现switch的优化

根据雇员类型计算薪资:

public Money calculatePay(Employee e) throws InvalidEmployeeType{
    switch (e.type){
        case COMMISSIONED:
            return calculateCommissionedPay(e);
        case HOURLY:
            return calculateHourlyPay(e);
        case SALARIED:
            return calculateSalariedPay(e);
        default:
            throw new InvalidEmployeeType(e.type);
    }
}

这里仅仅依赖了雇员类型一种操作,就有好几个问题了:
1. 函数太长,当有新的雇员类型,还会更长
2. 违反开闭原则,每添加新类型,就必须修改它
3. 违反了单一权责原则,它做了多件事情
更麻烦的是:
到处都有类似的调用函数,比如可能多处调用
isPayday(Employee e, Date date);

deliverPay(Employee e, Money pay);

事实上,这就是我的代码的现状。。。好惭愧。。。

下面来看下,对于这样的问题,该用什么样的思路去优化。

对每个类都会有同样的操作,比如isPayday(), deliverPay()等,不如把类的行为抽象出来到一个抽象类Employee中。在抽象工厂中使用switch语句为Employee的派生物创建适当的实体。

对于switch语句,我们的规矩是如果只出现一次,用于创建多态对象,而且隐藏在某个继承关系中,在其他系统看不到,就还能容忍。当然也要就事论事。

public abstract class Employee{
    public abstract boolean isPayday();
    public abstract Money calculatePay();
    public abstract void deliverPay(Money pay);
}
public interface EmployeeFactory{
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
public class EmployeeFactoryImpl implements EmployeeFactory{
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType{
        switch (r.type){
            case COMMISSIONED:
                return new CommissionedEmployee(r);
            case HOURLY:
                return new HourlyEmployee(r);
            case SALARIED:
                return new SalariedEmployee(r);
            default:
                throw new InvalidEmployeeType(r.type);
        }
    }
}

可以想象,用优化后的代码,再有新的类型加入时,业务程序是不用修改的,因为类型已隐藏在了抽象类中,返回给业务的都是抽象的Employee,无需考虑类型的变化,只是调用抽象类的方法即可。我们需要改动的只是再创建一个抽象类的实体类,在EmployeeFactoryImpl中多加一个switch分支。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值