前言
面向对象有人分为五大原则,分别为单一职责原则、开放封闭原则、依赖倒置原则、接口隔离原则、里氏替换原则。
也有人分为六大原则,分别为单一职责原则、开放封闭原则、依赖倒置原则、接口隔离原则、里氏替换原则、迪米特法则。
现在我们来介绍开放封闭原则,也叫开闭原则
开闭原则
1)概念
官方说法是 软件实体(模块、类、函数等)应该可以扩展,但是不可以修改。也就是说软件对扩展开放,对修改关闭。
需要说明的是,对修改关闭不是说软件设计不能做修改,只是尽量不要做不必要的修改。怎么才能做到呢?那就是有相应的扩展性。
其实,软件有相应的扩展性是好处,但是不能说每个地方都有扩展。反而造成了代码的臃肿。所以这里的扩展与修改关闭是有限制的。
开闭原则,可以说是其他五大原则的实现,也是面向对象设计的终极目标。我们也可以说成开闭原则是其他原则的核心。
说了这些概念性的东西,似懂非懂。我们可以试试从下面的例子来看看是否更加上心。
2)深入理解
开闭原则怎么能更深入的理解呢?还是说说我们身边的例子吧。
比如我们平常喝水用的一次性纸杯。平常人只是用来装水。喝完水就扔了。这就是这个纸杯的生命周期。纸杯这一生只完成了它的一个功能:装水。纸杯此时就很封闭了,没有什么扩展性。
此时,我看到身边有一支花苗,我想要拿回家种。但是没有容器呀? 啊?旁边不是有一个纸杯吗,可以用此纸杯来种这朵花苗。
纸杯有了它的另外一个扩展性,就是种花苗。
纸杯不仅有装水、种花苗的用途,以后还可以有装小垃圾、冲茶、回收等功能。对于以后这些功能,我们要想到他们的扩张性。
在纸杯只有一个装水的功能的时候,我们只写一个纸杯功能类,说纸杯能装水。但是以后有扩展呢?这一方面我们要预先判断。预先判断它以后可能会根据需求的变动而扩展。对于纸杯本来的装水功能,不能说不能修改,此功能只能在此函数、类中修改。这就是开闭原则的核心。
所以,纸杯在开闭原则所体现的是:尽量少修改,未来可能扩展的模块、类做好预算的判断。如果要修改,只能在此函数此类修改,不能牵涉到其他地方。
下面,我们用UML类图来直观地说明一下纸杯的设计吧。
当纸杯只有一个功能,装水时。有一个纸杯操作接口,有一个纸杯操作实现类。
当我们要添加一个功能 种花苗时,我们不也是加一个方法吗?如下:
当添加N个方法时,不也是在纸杯的操作接口上面添加N个方法吗?
我们想一想,此时已经背离了我们的开闭原则。因为每添加一个方法,都要在操作类上面做修改。所以,我们按照开闭原则,开做了以下合理的设计:
从上面可以看出,我们把纸杯的操作类,统一写成一个接口,每个不同的操作继承此接口来完成各自操作。我们还开到多了一个类,叫客户端类,其实此类也不难理解。也就是要最终操作纸杯的类。
3)其他例子
开闭原则其实在大话设计模式中说得非常好,让人通俗易懂。
它举了一个例子,我觉得说得非常好。是加减乘除法的例子。
开始需求是做一个加法的操作。后来继续加入减法、乘法、除法。
开始我们想加法以后可能会做一个需求变更:加入其它的算法法则。所以我们要有一个预判性,这个预判性会导致我们项目以后的扩展性,也会导致如果需求发生变更,程序修改的难易程度。
所以,我们要做一个算法法则的操作类,加减乘除法都继承此操作接口。再加一个算法法则的客户端类类操作此算法。
我们来上一下大话设计模式中的图:
4)总结
开闭原则是我们面向对象设计的目标,我们灵活地运用好此目标也不是易事。所以开闭原则要深入的理解,才能做好面向对象的编程,才能做一个好的软件。
其他链接:
此文转发,请注明出处,谢谢。
可以关注本人的公众号,多年经验的原创文章共享给大家。