面向对象原则之开闭原则

跟風遠走 提交于 2019-12-20 10:29:00

开闭原则

基本介绍

开闭原则(Open-Closed Principle, OCP),是面向对象的可复用设计的第一块基石,它是最重要的面向对象设计原则,是由Bertrand Meyer于1988年提出,意为一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

任何软件系统都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延展性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在Java编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

代码示例

下面是一个未经重构的计算机器类:

public class CalculatorUtils {

    /**
     * 计算
     *
     * @param num1 数字1
     * @param num2 数字2
     * @param calculationMode 计算方式
     * @return
     */
    public BigDecimal calculation(BigDecimal num1, BigDecimal num2, String calculationMode) {
        if ("+".equals(calculationMode)) {
            return num1.add(num2);
        } else if ("-".equals(calculationMode)) {
            return num1.subtract(num2);
        } else if ("*".equals(calculationMode)) {
            return num1.multiply(num2);
        } else if ("/".equals(calculationMode)) {
            return num1.divide(num2);
        }
        return null;
    }
}

上述的计算器类,有一个calculation方法是用来计算结果的,由客户端来选择需要使用哪种计算方式,因此里面使用了很多if else判断,如果我需要增加一种计算方式则需要修改此类,增加新的逻辑判断,从而违反了开闭原则。

下面我们使用抽象的方式来对此类进行重构,使其需要扩展的时候,无需修改原有代码,以新增类的方式进行扩展,满足了开闭原则。

以下是重构后的代码:

public class CalculatorUtils {

    /**
     * 计算
     *
     * @param num1 数字1
     * @param num2 数字2
     * @param calculator 计算方式
     * @return
     */
    public BigDecimal calculation(BigDecimal num1, BigDecimal num2, ICalculator calculator) {
        return calculator.getResult(num1,num2);
    }
}

public interface ICalculator {
    BigDecimal getResult(BigDecimal num1, BigDecimal num2);
}

public class CalculationAdd implements ICalculator {
    @Override
    public BigDecimal getResult(BigDecimal num1, BigDecimal num2) {
        return num1.add(num2);
    }
}


public class CalculationSubtract implements ICalculator {
    @Override
    public BigDecimal getResult(BigDecimal num1, BigDecimal num2) {
        return num1.subtract(num2);
    }
}

public class CalculationMultiply implements ICalculator {
    @Override
    public BigDecimal getResult(BigDecimal num1, BigDecimal num2) {
        return num1.multiply(num2);
    }
}

public class CalculationDivide implements ICalculator {
    @Override
    public BigDecimal getResult(BigDecimal num1, BigDecimal num2) {
        return num1.divide(num2);
    }
}

我们对计算方式抽象成了接口ICalculator,针对不同的计算方式可以拥有不同的实现,CalculatorUtils类的calculation方法直接传入相应的计算方式实现,无需复杂的逻辑判断,即使以后需要增加计算方式,也只需要增加一个实现类去实现ICalculator接口即可,无需改动现有类的代码,满足了对扩展开放,对修改关闭的要求,符合开闭原则。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!