开闭原则定义
照例还是说一下开闭原则的基本定义,开闭原则第一次被提出来是在1988年,在Bertrand Meyer的《面向对象软件架构》中写道:
各种软件实体(类、模块、方法等)应当对扩展保留开发的可能性,而对他们的修改保持关闭(拒绝)
software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
在软件的生命周期中变化和迭代一定是不断发生的,而我们的主观感情是确实希望我能够一次将业务的本质理解和实现到位,再也不要有变化了。我们能做的就是坦然的接受这个事实,“拥抱变化”,在设计和开发软件时,尽量适应这些变化,以此来提供项目的灵活性。
开闭原则告诉我们,应当尽量通过扩展软件的方式来应对变化,满足新的需求,而不是通过修改现有的代码来达到目标。
An entity can allow its behaviour to be extended without modifying its source code.
开闭原则背后的思考
开闭原则的背后,除了强调扩展的可能性,更是想推崇模块的稳定性。要做到这样,需要在设计之前就要花很多经理去理解业务流程,去了解更多可能的业务场景。这样才能去抽象出不变的部分是什么,这部分通常包括流程逻辑和核心业务逻辑,是经得起推敲的,这部分的变更也应当是极其慎重的。
从笔者角度来看,如果软件核心的部分都是需要很大的变化,其实这个设计本身就有问题或者已经不能再满足业务的需要了,那么适当的选择应当是废弃该软件模块(或业务模块),转而设计并实现新的软件模块,这和持续重构(Continuous Reconstruction)的思想是一致的。
当然,这并不意味着软件模块的设计可以变得仓促而随意,这要视软件实际可能的生命周期而定。一个给客户(或投资人)演示的原型软件和一个已经面向大型客户需要在未来长期(3年、5年或10年)的软件,所需要的稳定性和扩展性是不可同日而语的。前者大可以照着功能需要直接实现就可以;而后者则需要考虑业务流程调整、访问量变化、存储量变化、部署环境变化、三方服务商定制、甚至技术栈切换等各个方面的可能性,同时每种情况在不同行业的软件是否会出现、出现的接口都可能不一样。
大家需要知道,开闭原则是所有其他面向对象原则的基础,比如单一职责是找到模块中不变的部分,构建出单一的职责;里式替换原则则告诉我们不要破坏继承体系(不要动上层的源代码);依赖导致通常使用接口编程来进行实现;接口分割原则强调设计接口要经简单一,调用接口不会产生额外的依赖。因此开闭原则是总纲,而其他原则从不同的角度去介绍,该如何构建稳定、可靠、可维护的实体(模块、类、方法等);如何去提升实体的灵活性;如何在依赖过程中不产生副作用。
因此在本章节,笔者将不会展示具体的代码实例,因为像前面说的,开闭原则是总纲,单个的例子都会显得以偏概全,我们在其他原则的介绍中将不断反过来映照到这个原则。去论证开闭原则于架构、与系统设计、与代码实现的重要参考意义。
冯·诺依曼体系
在冯·诺依曼体系中,只引入了三种基础组件:中央处理器、存储、输入输出设备
这三个基础组件定义了指令和指令的执行流程,应该如何存储和缓存。就是这么精简的结构,他没有尝试“解决任何问题”,而是“所有问题都可以基于这个体系去解决”。你可以扩展指令序列,扩展输入输出设备,可以扩展我们的存储设备,这些都是计算机开放性的提现;而基础组件内部则是不允许被修改的。
笔者原文发布在CSDN,欢迎点击查看:OOP设计原则SOLID--开闭原则Open-Close Principle
也可以关注笔者博客(请给我一根烟的时间https://blog.csdn.net/mytream),查看更多个人心得和分享