1.定义
一个软件实体如类、模块和函数等应该对扩展开放(open for extension),对修改关闭(closed for modification)。模块应尽量在不修改原(是"原",指原来的代码)代码的情况下进行扩展。
2.开闭原则的意义
我们在设计、开发任何软件系统时,都不可能指望软件需求一经确认便不再变化。在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
1)对软件测试的影响
软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
2)可以提高代码的可复用性
粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
3)可以提高软件的可维护性
遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
3.使用说明
需求1:设计一个计算器,具备加法计算功能
编码设计1:
class Cal{
private double x;
private double y;
public double add(double x, double y){
return x+y;
}
}
需求2:新增功能:减法
编码设计2:
class Cal{
private double x;
private double y;
public double add(double x, double y){
return x + y;
}
public double subtract(double x, double y){
return x - y;
}
}
针对需求,我们新增了一个减法方法,嗯,看起来还不错哦,很easy的实现了需求,好开心。
sorry, 老板、客户、产品经理又来提新需求了。。。。。
需求3:新增功能:乘法
class Cal{
private double x;
private double y;
public double add(double x, double y){
return x + y;
}
public double subtract(double x, double y){
return x - y;
}
public double multiply(double x, double y){
return x * y;
}
}
通过添加方法的方式,我们再次满足了需求。
过几天,新的需求又来了,又来了,又来了。Cal类最后已经被我们修改的满目疮痍了,早已不在是当初那个人畜无害的加法计算器了。
上面的场景,相信很大概率上对于我们这些码农们都是一股很熟悉的味道,一点也不陌生。如果在设计编码之初,我们就能对后续这一些列的变化都能预料到,那该多么完美,但是显然这是不现实的。所以在最初编码时,我们有意识的梳理最可能变化的种类,然后构造抽象来隔离这些变化。例如,针对上述场景,在最开始的时候,我们就抽象出一个运算类,后续所有针对操作方法业务需求新增场景,通过增加相应子处理类便可解决问题。