开放-封闭原则的定义是——程序的实体对象(模块、类、函数等)应该可以进行扩展,但不应该可以修改。
开放-封闭原则具有两个特征:
1.对于扩展是开放的;
2.对于修改是闭合的。
开放-封闭原则是面向对象开发中所有设计原则的核心。
当经过实践,在面向对象编程时,如果要实现一个新的功能,添加一个新类来完成往往比修改现有的类更加方便和安全。这种思维就是所说的开放-封闭原则。
所谓的添加而不是修改,就是指对已有程序的扩展优先采用添加类或者模块的方式来进行,而不是通过修改现有的类或者模块,这样做的原因是因为软件设计的本身所追求的目标就是封装变化,降低耦合,而开放-封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候也是为实现这一目标服务的。例如里氏替换实现最佳的,正确的集成层次,就可以保证不会违反开放-封闭原则。
“需求总是在变化的”、“世界上没有一个软件是一成不变的”,这些言论正是对软件需求最经典的表达。从中透露出来的关键意思就是,对于软件的设计者来说,应该在不需要对原有的 系统进行修改的情况下,实现更加灵活的系统扩展。
事实上,完全封闭的系统是不存在的,无论模块怎么实现封闭,到最后,总还是有一些无法封闭的变化,对应的思路就是:既然不能做到绝对的封闭,我们就选择对那些变化进行封闭,那些进行隔离,然后对那些无法封闭的变化抽象出来,进行隔离,并允许扩展,尽可能的减少系统的开发,当系统变化出现时,及时作出反应。
举个例子:
/**
* Author:小青
* Time:2017-8-27
* Function:动物类
*
*/
public class Animal{
public void Breath(){
System.out.println("动物会呼吸");
}
}
/**
* Author:小青
* Time:2017-8-27
* Function:猫
*
*/
public class Cat extends Animal{
public void CatchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Client{
public sttaic void main(String[] args){
Cat cat = new Cat();
cat.Breath();
cat.CatchMouse();
}
}
现在业务发生了变化,汤姆不仅会抓老鼠还在训练后,学会了游泳
/**
* Author:小青
* Time:2017-8-27
* Function:汤姆猫
*
*/
public class Tom extends Cat{
public void Swimming(){
System.out.println("汤姆在训练后学会了游泳");
}
}
public class Client{
public sttaic void main(String[] args){
Cat cat = new Cat();
cat.Breath();
cat.CatchMouse();
Tom tom = new Tom();
tom.Breath();
tom.CatchMouse();
tom.Swimming();
}
}
上面通过添加一个新的类,完成了业务,但是客户端的代码也进行了少量的修改,那么这种情况下,设计人员就应该对自己设计的模块觉得选择那种变化封闭,比较好的方式就是等到变化发生时立刻采取行动。
实现开放-封闭原则的核心就是面向抽象编程,而不是面向具体编程,因为抽象相对来说是稳定的。让类去依赖固定的抽象,所以对于修改来说就是封闭的;而通过面向对象的继承以及多态,可以实现对抽象体的集成,通过重写方法来改变固定行为,从而实现新的扩展方法,对于扩展来说就是开放的。这是实施开放-封闭原则的固有思路,同时也是建立在里氏替换原则和合成/聚合复用原则上的。
接下来以银行业务员分类,比较实现开发-封闭原则和未实现的区别:
/**
* Author:小青
* Time:2017-8-27
* Function:银行业务员-未实现开放-封闭原则
*
*/
public class BankWorker{
//转账业务员
public void saving(){
system.out.println("存款");
}
//取款业务员
public void drawing(){
system.out.println("取款");
}
//转账业务员
public void zhuanzhuang(){
system.out.println("转账");
}
//基金的申购员
public void jijjin(){
system.out.println("基金申购");
}
}
public class Client{
public sttaic void main(String[] args){
BankWorker bankworker = new BankWorker();
bankworker.saving();
bankworker.drawing();
bankworker.zhuanzhuang();
bankworker.jijjin();
}
}
实现后的代码
/**
* Author:小青
* Time:2017-8-27
* Function:银行业务员接口
*
*/
public interface BankWorker{
public void operation();
}
/**
* Author:小青
* Time:2017-8-27
* Function:存款业务员
*
*/
public class SavingBankWorker implements BankWorker{
public void operation(){
system.out.println("存款");
}
}
/**
* Author:小青
* Time:2017-8-27
* Function:取款业务员
*
*/
public class DrawingBankWorker implements BankWorker{
public void operation(){
system.out.println("取款");
}
}
/**
* Author:小青
* Time:2017-8-27
* Function:转账业务员
*
*/
public class ZhuanzhuangBankWorker implements BankWorker{
public void operation(){
system.out.println("转账");
}
}
/**
* Author:小青
* Time:2017-8-27
* Function:基金申购业务员
*
*/
public class JijingBankWorker implements BankWorker{
public void operation(){
system.out.println("基金申购");
}
}
public class Client{
public sttaic void main(String[] args){
BankWorker bankWorker = new SavingBankWorker();
bankWorker.operation();
BankWorker bankWorker2 = new DrawingBankWorker();
bankWorker2.operation();
BankWorker bankWorker3 = new ZhuanzhuangBankWorker();
bankWorker3.operation();
BankWorker bankWorker4 = new JijingBankWorker();
bankWorker4.operation();
}
}
开放-封闭原则可以扩展已有的软件系统提供新的行为以满足软件的新需求,使变化中的软件有一定的适应性和灵活性,对已有的软件模块,特别是最重要的抽象模块不能再修改,使得软件系统有一定的稳定性和延续性。
以上内容,整理自刘径舟,张玉华编著的《设计模式其实很简单》读书笔记,欢迎转载.