SOLID原则-开闭原则

开闭原则定义

Robert C. Martin 认为这个原则是面向对象设计中最重要的一个原则,但他不是第一个定义这个原则的人,Bertrand Meyer 在1988年写的一本书《Object-Oriented Software Construction》,其中解释了开闭原则:软件实体(类,模块,方法等)应该对扩展开放,对修改关闭
这个原则的主要思想是很棒的,它告诉我们写代码时,当添加新功能时不应该修改现有的代码,这样阻止了我们修改一处代码所依赖它的代码都要修改。但是有点可惜的是,Bertrand Mayer 当时建议用 继承 去实现这个原则,具体描述如下:
“一个类是被关闭的,因为它已经被编译放在一个类库里,后面被其他代码引入调用,但是它也是开放的,因为一个新类可以继承它,添加新特性,添加子类,不需要修改原有的父类和调用父类的代码”。
这个思想流行了一些年,直到有人对这个原则提出了更好的解释,例如,Robert C. Martin 在他的文章里和 Joshua Bloch 在他的书 《Effective Java》都提到,通过继承的方式,引入了子类和父类的紧耦合,子类需要依赖父类的实现细节。
因此,Robert C. Martin ,还有其他人对开闭原则重新做了定义,利用多态实现开闭原则,使用接口替代继承的方式,通过类实现接口的方式来扩展新功能,接口对修改关闭。
这种实现方式的主要好处是接口引入了一个新的抽象实现松耦合,接口实现类是相互独立的,之间不存在共享代码。如果你认为两个实现类之间存在共享代码是有好处的,你可以通过继承或者组合的方式实现。

样例

编写一个计算器程序,支持加减乘除操作,首先我们定义一个顶级接口 CalculatorOperation

public interface CalculatorOperation {}

定义一个加法 类,实现两个数字的求和计算

public class Addition implements CalculatorOperation {
    private double left;
    private double right;
    private double result = 0.0;
 
    public Addition(double left, double right) {
        this.left = left;
        this.right = right;
    }
 
    // getters and setters
 
}

类似减法 代码,

public class Subtraction implements CalculatorOperation {
    private double left;
    private double right;
    private double result = 0.0;
 
    public Subtraction(double left, double right) {
        this.left = left;
        this.right = right;
    }
 
    // getters and setters
}

定义一个代表计算器的类,调用加法和减法

public class Calculator {
 
    public void calculate(CalculatorOperation operation) {
        if (operation == null) {
            throw new InvalidParameterException("Can not perform operation");
        }
 
        if (operation instanceof Addition) {
            Addition addition = (Addition) operation;
            addition.setResult(addition.getLeft() + addition.getRight());
        } else if (operation instanceof Subtraction) {
            Subtraction subtraction = (Subtraction) operation;
            subtraction.setResult(subtraction.getLeft() - subtraction.getRight());
        }
    }
}

上面的例子,看上去没什么问题,但是不符合开闭原则,当有新的功能需添加时,我们需要修改类 Calculator
现在我们把上面的例子稍作修改,让它符合开闭原则,首先在接口 CalculatorOperation 中添加方法 perform

public interface CalculatorOperation {
    void perform();
}

加法的实现类如下:

public class Addition implements CalculatorOperation {
    private double left;
    private double right;
    private double result;
 
    // constructor, getters and setters
 
    @Override
    public void perform() {
        result = left + right;
    }
}

我们再加一个除法的实现类

public class Division implements CalculatorOperation {
    private double left;
    private double right;
    private double result;
 
    // constructor, getters and setters
    @Override
    public void perform() {
        if (right != 0) {
            result = left / right;
        }
    }
}

Calculator 基于接口 CalculaotrOperatotion 实现,当有新的实现时,无须更改此处的代码

public class Calculator {
 
    public void calculate(CalculatorOperation operation) {
        if (operation == null) {
            throw new InvalidParameterException("Cannot perform operation");
        }
        operation.perform();
    }
}

你可能感兴趣的:(面向对象分析和设计,java,面向对象编程)