开闭原则浅析

开闭原则(OCP):一个软件实体(类、模块、函数)都应该对扩展开放,对修改封闭。在软件的生命周期内,因为变化、升级和维护等原因都会对原有代码进行修改,可能给原有代码引入错误。此时应尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有代码来实现。看下面一个最简单的代码例子。

package com.haozz.demo.fee;

import org.springframework.stereotype.Service;

/**
 * <p>Coding</p>
 *
 * @author haozz
 * @version $Id: FeeCalculatorService.java, v 0.1 2019/1/8 21:36 haozz Exp $
 */
@Service
public class FeeCalculatorService {

    /**
     * @Author haozz
     * @Date 2019/1/8 21:45
     * @Param [type, count]
     * @return double
     * @Description 根据不同的用户身份,计算打折后的金额
     */
    public double calculate(String type, double count){
        if(type.equals("vip")){
            return count * 0.8;
        }else if(type.equals("normal")){
            return count * 0.98;
        }else {
            return count * 0.99;
        }
    }
}

这是一个非常简单的根据不同的用户身份,计算消费金额的Service。但是这样的代码是不满足开闭原则的,因为如果某一种用户的打折方案需要修改,或者需要新增一种用户身份以及打折方案,就需要修改这里的计算方法。而一般的计算金额的方法逻辑都不会是上述代码那么简单,所以此时修改核心的计算代码是非常不可取的方法。为了使代码符合开闭原则的标准,我们先做如下的改进:

首先,新增一个折扣的interface:

package com.haozz.demo.fee;

/**
 * <p>Coding</p>
 *
 * @author haozz
 * @version $Id: DemoClass.java, v 0.1 2019/1/8 21:51 haozz Exp $
 */
public interface DiscountInterface {

    String type();

    double discount(double count);
}

然后新增不同的用户身份的折扣class,并实现上面的接口:

package com.haozz.demo.fee;

import org.springframework.stereotype.Service;

/**
 * <p>Coding</p>
 *
 * @author haozz
 * @version $Id: VipDiscount.java, v 0.1 2019/1/8 21:52 haozz Exp $
 */
@Service
public class VipDiscount implements DiscountInterface {
    @Override
    public String type() {
        return "vip";
    }

    @Override
    public double discount(double count) {
        return count * 0.8;
    }
}
package com.haozz.demo.fee;

import org.springframework.stereotype.Service;

/**
 * <p>Coding</p>
 *
 * @author haozz
 * @version $Id: NormalDiscount.java, v 0.1 2019/1/8 21:54 haozz Exp $
 */
@Service
public class NormalDiscount implements DiscountInterface{

    @Override
    public String type() {
        return "normal";
    }

    @Override
    public double discount(double count) {
        return count * 0.98;
    }
}

此时,在FeeCalculatorService类的计算方法中,只需做如下的修改即可:

package com.haozz.demo.fee;

import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * <p>Coding</p>
 *
 * @author haozz
 * @version $Id: FeeCalculatorService.java, v 0.1 2019/1/8 21:36 haozz Exp $
 */
@Service
public class FeeCalculatorService {

    //定义一个map,存储用户打折类
    HashMap<String,DiscountInterface> map = new HashMap<>();

    //类初始化的时候,通过Spring将所有的用户打折类注入到构造函数中
    public FeeCalculatorService(List<DiscountInterface> list) {
        for (DiscountInterface discountInterface : list) {
            map.put(discountInterface.type(),discountInterface);
        }
    }

    /**
     * @return double
     * @Author haozz
     * @Date 2019/1/8 21:45
     * @Param [type, count]
     * @Description 根据不同的用户身份,计算打折后的金额
     */
    public double calculate(String type, double count) {
        return map.get(type).discount(count);
    }
}

这样代码就改写完成了。这里我们使用了策略模式,首先我们为不同的用户身份定义了不同的打折方案类,并在discount方法进行计算打折后的金额。在FeeCalculatorService中,通过Spring将所有的DiscountInterface的实现类注入到构造方法的一个list中,因为我们定义的用户打折类都交给了Spring管理,所以Spring在初始化的时候是可以拿到这些类的。然后将他们放在一个定义好的HashMap中。当进行具体的计算方法是,只需要在map中获取指定用户身份的用户打折类,并执行其中的discount方法。这样一来,当需求变化需要修改某一用户打折方案,或者新增用户类型时,我们只需要修改或者新增对应的用户打折类,而不需要对计算方法本身进行修改。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值