开闭原则的定义
开闭原则(Open Closed Principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification),这就是开闭原则的经典定义。
这里的软件实体包括以下几个部分:
- 项目中划分出的模块
- 类与接口
- 方法
开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。
开闭原则的作用
开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。具体来说,其作用如下。
1. 对软件测试的影响
软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
应当对扩展开放,对修改关闭。
2. 可以提高代码的可复用性
粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
3. 可以提高软件的可维护性
遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
开闭原则的实现方法
可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。换言之,要针对接口编程,而不是针对实现编程。
因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
样例说明:
下面以某软件的操作按钮样式为例介绍加深理解:
某软件公司的按钮样式现在是圆角型,为了符合市场扁平化的风格,现在要对所有界面的按钮换为矩形扁平化的按钮。
在本实例中,窗体的显示针对每一个按钮类编程,因此要改变按钮样式,不得不修改窗体显示源代码,然后才能实现需求,这就违反了开闭原则,新增一个功能要修改原有正在使用的程序。
为了满足开闭原则。具体做法如下:
- 增加一个抽象按钮类AbstractButton,将各种具体按钮样式类作为其子类;
- 窗体显示类针对抽象按钮类进行编程,由客户端来决定使用哪种具体按钮样式。
抽象按钮类:
package com.wry.principle.openclose.form;
public abstract class AbstractButton {
public abstract void display();
}
圆角按钮:
package com.wry.principle.openclose.form;
public class CircleButton extends AbstractButton {
@Override
public void display() {
System.out.println(" 圆角按钮");
}
}
矩形按钮类:
package com.wry.principle.openclose.form;
public class RectangleButton extends AbstractButton {
@Override
public void display() {
System.out.println(" 长方形扁平按钮");
}
}
窗体使用类:
package com.wry.principle.openclose.form;
public class WinForms {
private AbstractButton button;
public WinForms(AbstractButton button) {
this.button = button;
}
public void display(){
System.out.println("----------窗体---------");
button.display();
System.out.println("----------窗体---------");
}
}
客户端使用:
package com.wry.principle.openclose.form;
public class Client {
public static void main(String[] args) {
AbstractButton button;
WinForms forms;
//显示圆角按钮
button=new CircleButton();
forms=new WinForms(button);
forms.display();
//显示矩形扁平按钮
button=new RectangleButton();
forms=new WinForms(button);
forms.display();
}
}
输出结果: