【设计原则】开闭原则(对扩展开放、对修改关闭)
开闭原则的英文全称是 Open Closed Principle,简写为 OCP。它的英文描述是:software entities (modules, classes, functions, etc.) should be open for extension , but closed for modification。即:软件实体(模块、类、方法等)应该“对扩展开放、对修改关闭”。添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。
下面根据开闭原则重构以下代码(拆分check方法):
public class Alert {private AlertRule rule;private Notification notification;public Alert(AlertRule rule, Notification notification) {this.rule = rule;this.notification = notification;}public void check(String api, long requestCount, long errorCount, long durationOfSeconds) {long tps = requestCount / durationOfSeconds;if (tps > rule.getMatchedRule(api).getMaxTps()) {notification.notify(NotificationEmergencyLevel.URGENCY, "...");}if (errorCount > rule.getMatchedRule(api).getMaxErrorCount()) {notification.notify(NotificationEmergencyLevel.SEVERE, "...");}}
}
重构思路:
(1)将 check() 函数的多个入参封装成 ApiStatInfo 类;
(2)引入 handler 的概念,将 if 判断逻辑分散在各个 handler 中(使用责任链模式的变体,所有handler节点都遍历执行)。
public class Alert {private List<AlertHandler> alertHandlers = new ArrayList<>();public void addAlertHandler(AlertHandler alertHandler) {this.alertHandlers.add(alertHandler);}public void check(ApiStatInfo apiStatInfo) {for (AlertHandler handler : alertHandlers) {handler.check(apiStatInfo);}}
}@Data
public class ApiStatInfo {private String api;private long requestCount;private long errorCount;private long durationOfSeconds;
}public abstract class AlertHandler {protected AlertRule rule;protected Notification notification;public AlertHandler(AlertRule rule, Notification notification) {this.rule = rule;this.notification = notification;}public abstract void check(ApiStatInfo apiStatInfo);
}public class TpsAlertHandler extends AlertHandler {public TpsAlertHandler(AlertRule rule, Notification notification) {super(rule, notification);}@Overridepublic void check(ApiStatInfo apiStatInfo) {long tps = apiStatInfo.getRequestCount()/ apiStatInfo.getDurationOfSeconds();if (tps > rule.getMatchedRule(apiStatInfo.getApi()).getMaxTps()) {notification.notify(NotificationEmergencyLevel.URGENCY, "...");}}
}public class ErrorAlertHandler extends AlertHandler {public ErrorAlertHandler(AlertRule rule, Notification notification){super(rule, notification);}@Overridepublic void check(ApiStatInfo apiStatInfo) {if (apiStatInfo.getErrorCount() > rule.getMatchedRule(apiStatInfo.getApi()).getMaxErrorCount()) {notification.notify(NotificationEmergencyLevel.SEVERE, "...");}}
}
重构之后的代码更加灵活和易扩展。如果我们要想添加新的告警逻辑,只需要基于扩展的方式创建新的 handler 类即可,不需要改动原来的 check() 函数的逻辑。而且,我们只需要为新的 handler 类添加单元测试,老的单元测试都不会失败,也不用修改。
在重构之后的 Alert 代码中,我们的核心逻辑集中在 Alert 类及其各个 handler 中,当我们在添加新的告警逻辑的时候,Alert 类完全不需要修改,而只需要扩展一个新 handler 类。如果我们把 Alert 类及各个 handler 类合起来看作一个“模块”,那模块本身在添加新的功能的时候,完全满足开闭原则。
并且,我们要认识到,添加一个新功能,不可能任何模块、类、方法的代码都不“修改”,这个是做不到的。类需要创建、组装、并且做一些初始化操作,才能构建成可运行的的程序,这部分代码的修改是在所难免的。我们要做的是尽量让修改操作更集中、更少、更上层,尽量让最核心、最复杂的那部分逻辑代码满足开闭原则。
实际上,多态、依赖注入、基于接口编程,以及前面提到的抽象意识,说的都是同一种开闭原则设计思路,只是从不同的角度、不同的层面来阐述而已。这也体现了“很多设计原则、思想、模式都是相通的”这一思想。
“唯一不变的只有变化本身”。没必要为一些遥远的、不一定发生的需求去做过度设计。最合理的做法是,对于一些比较确定的、短期内可能就会扩展,或者需求改动对代码结构影响比较大的情况,或者实现成本不高的扩展点,在编写代码的时候之后,我们就可以事先做些扩展性设计。
【设计原则】开闭原则(对扩展开放、对修改关闭)相关推荐
- 如何做到“对扩展开放、修改关闭”?
我们来学习 SOLID 中的第二个原则:开闭原则.我个人觉得,开闭原则是 SOLID 中最难理解.最难掌握,同时也是最有用的一条原则. 之所以说这条原则难理解,那是因为,"怎样的代码改动才被 ...
- 面向对象软件设计的“开—闭”原则
1.什么是开闭原则 "开-闭"原则是指软件实体应当对扩展性开放,对修改关闭.即软件实体应该在不修改的前提下扩展,这个原则实际上为软件设计指明了目标.我们知道软件设计 ...
- 【设计模式】软件设计七大原则 ( 开闭原则 )
文章目录 一.开闭原则简介 二.开闭原则代码示例 1.商品接口 2.普通商品类 3.折扣商品类 4.测试类 一.开闭原则简介 开闭原则 : 定义 : 一个 软件实体 , 类 / 模块 / 函数 , 对 ...
- 带你认识六种设计原则(开闭原则、里氏代换原则、依赖倒转原则....)
前言 1. 设计原则 1.1. 开-闭原则 1.2. 里氏代换原则 1.3. 依赖倒转原则 1.4. 接口隔离原则 1.5. 合成/聚合原则 1.6. 迪米特法则 前言 学习设计模式之前先要了解其中的 ...
- 六大设计原则--开闭原则
定义 software entities like classes, modules and functions should be open for extension but closed for ...
- 一周技术学习笔记(第67期)-CPU的设计跟开闭原则有关系吗
你能想到CPU的设计是开闭原则的设计吗 说CPU的设计很符合软件设计的开闭原则,估计一般的同学肯定不会这样意识到.其实我也一样不太可能把它们能够想在一起,并将它们关联起来. 可确实就这样发生了.实际上 ...
- 六大设计模式原则-开闭原则
一.开闭原则定义 开闭原则是面向对象的可复用设计的第一块基石,是最重要的面向对象设计原则.定义如下: 开闭原则(Open-Closed Principle, OCP):一个软件实体应当对扩展开放,对修 ...
- 设计模式6大原则-开闭原则
设计模式6大原则-开闭原则 定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则理念就是当需求改变时,希望在不改变原有代码的前提下,通过扩展模块.函数来满足新需求. 开闭原则是其他 ...
- 设计模式之王者原则 开闭原则
设计模式之王者原则 开闭原则 为什么说 它--开闭原则是王者原则呢? 因为所有原则都是围绕它来实现的,怎么说呢,为什么会有这么多原则呢,都是为了完成它,只要实现它你的代码就不会有什么大的问题 一.定 ...
- 设计一个扩展自抽象类geometricobject的新的triangle类_面向对象设计原则之开放封闭原则(开闭原则OCP)...
(1) 定义 一个软件实体(类.模块.函数等),对于扩展是开放的,对于更改是封闭的. 对于扩展是开放的:这意味着模块的行为是可以扩展的.当应用的需求发生改变时,我们可以对模块进行扩展,比如增加新的类或 ...
最新文章
- 资源 | 2018年值得关注的200场机器学习会议(建议收藏)
- vue 圆形百分比进度条_快速构建一个圆形的进度条
- 《追风行动》有点儿意思
- vue项目和react项目中禁止eslint
- 来一个可能防止恶意采集和爬虫的SH
- vscode php函数提醒,解决vscode格式保存后出现的问题
- 中毒后重装系统该注意的几点
- 使用Python把树莓派改造成一个语音助手
- Sql Server 2005 64位安装包
- linux系统date命令(时间戳与日期相互转换)
- 研究生新人如何高效读论文-方法积累笔记
- Android Red5视频通讯第一篇:连接服务器
- 解决AssertionError Torch not compiled with CUDA enabled问题
- 华科计院数据库课程笔记
- 保存rdl文件到报表服务器,在SQL服务器上将RDL报表导出成Excel XLS XLSX SpreadsheetML格式...
- 照片的35x45,300dpi怎么弄
- 安装angular脚手架
- NOIP 2015 简记
- mp4文件播放不了怎么办?
- ctf php 流量分析题,CTF平台hackit题目分析与解答