如何修改代码又不违背开闭原则呢?看这里

Quartus II 13.1 出现 ‘‘can‘t find design entity <Filename>‘‘ 问题的解决方法 Quartus II 13.1 出现 ''can't find design entity '' 问题的解决方法 阅读详情

前言

看了前一篇重构之后的代码,你可能还会有疑问:

在添加新的告警逻辑时,改动二(添加新的 handler 类)是基于扩展而非修改的方式来完成的,但改动一、三、四貌似不是基于扩展而是基于修改的方式来完成的,

那改动一、三、四不就违背了开闭原则吗?

public class Alert { // 代码未改动... }

public class ApiStatInfo {// 省略 constructor/getter/setter 方法

  private String api;

  private long requestCount;

  private long errorCount;

  private long durationOfSeconds;

  private long timeoutCount; // 改动一:添加新字段

}

public abstract class AlertHandler { // 代码未改动... }

public class TpsAlertHandler extends AlertHandler {// 代码未改动...}

public class ErrorAlertHandler extends AlertHandler {// 代码未改动...}

// 改动二:添加新的 handler

public class TimeoutAlertHandler extends AlertHandler {// 省略代码...}

public class ApplicationContext {

  private AlertRule alertRule;

  private Notification notification;

  private Alert alert;



  public void initializeBeans() {

    alertRule = new AlertRule(/*. 省略参数.*/); // 省略一些初始化代码

    notification = new Notification(/*. 省略参数.*/); // 省略一些初始化代码

    alert = new Alert();

    alert.addAlertHandler(new TpsAlertHandler(alertRule, notification));

    alert.addAlertHandler(new ErrorAlertHandler(alertRule, notification));

    // 改动三:注册 handler

    alert.addAlertHandler(new TimeoutAlertHandler(alertRule, notification));

  }

  //... 省略其他未改动代码...

}

public class Demo {

  public static void main(String[] args) {

    ApiStatInfo apiStatInfo = new ApiStatInfo();

    //... 省略 apiStatInfo 的 set 字段代码

    apiStatInfo.setTimeoutCount(289); // 改动四:设置 tiemoutCount 值

    ApplicationContext.getInstance().getAlert().check(apiStatInfo);

}

我们先来分析一下改动一:往 ApiStatInfo 类中添加新的属性 timeoutCount。

  1. 我们不仅往 ApiStatInfo 类中添加了属性,还添加了对应的 getter/setter 方法。那这个问题就转化为:给类中添加新的属性和方法,算作 “修改” 还是 “扩展”?

我们再一块回忆一下开闭原则的定义:软件实体(模块、类、方法等)应该 “对扩展开放、对修改关闭”。

从定义中,我们可以看出,开闭原则可以应用在不同粒度的代码中,可以是模块,也可以是类,还可以是方法(及其属性)。
同样一个代码改动,在粗代码粒度下,被认定为 “修改”,在细代码粒度下,又可以被认定为 “扩展”。

  1. 比如,改动一,添加属性和方法相当于修改类,在类这个层面,这个代码改动可以被认定为 “修改”;但这个代码改动并没有修改已有的属性和方法,在方法(及其属性)这一层面,它又可以被认定为 “扩展”。

我们回到这条原则的设计初衷:只要它没有破坏原有的代码的正常运行,没有破坏原有的单元测试,我们就可以说,这是一个合格的代码改动。

接下来再来分析一下改动三和改动四:在 ApplicationContext 类的 initializeBeans () 方法中,往 alert 对象中注册新的 timeoutAlertHandler;在使用 Alert 类的时候,需要给 check () 函数的入参 apiStatInfo 对象设置 timeoutCount 的值。

  1. 这两处改动都是在方法内部进行的,不管从哪个层面(模块、类、方法)来讲,都不能算是 “扩展”,而是地地道道的 “修改”。

  2. 不过,有些修改是在所难免的,是可以被接受的。
    在重构之后的 Alert 代码中,我们的核心逻辑集中在 Alert 类及其各个 handler 中,当我们在添加新的告警逻辑的时候,Alert 类完全不需要修改,而只需要扩展一个新 handler 类。如果我们把 Alert 类及各个 handler 类合起来看作一个 “模块”,那模块本身在添加新的功能的时候,完全满足开闭原则。

而且,我们要认识到,添加一个新功能,不可能任何模块、类、方法的代码都不 “修改”,这个是做不到的。类需要创建、组装、并且做一些初始化操作,才能构建成可运行的的程序,这部分代码的修改是在所难免的。我们要做的是尽量让修改操作更集中、更少、更上层,尽量让最核心、最复杂的那部分逻辑代码满足开闭原则。

更多java原创阅读:https://javawu.com

医疗设备安规入门:一张图搞懂BF型设备的MOOP/MOPP绝缘路径(附GB 9706.1附录解析) 本文深入解析了BF型医疗设备的MOOP/MOPP绝缘路径设计,结合GB 9706.1标准附录J的实战应用,帮助工程师快速掌握医疗设备安规要点。通过典型绝缘路径图分析,详细对比了MOOP与MOPP的防护差异,并提供了海拔修正、漏电流测试等关键设计指南,助力医疗设备安全合规。 阅读详情

相关推荐

从理论到代码:如何用随机矩阵理论(RMT)优化你的微生物共现网络分析?

本文详细介绍了如何利用随机矩阵理论(RMT)优化微生物共现网络分析,解决传统阈值法的主观性和不稳定性问题。通过R语言实现端到端的分析流程,包括矩阵标准化、本征值谱分析和自动阈值确定,显著提升网络构建的准确性和可靠性。该方法特别适用于高通量测序数据,能自动识别噪声与真实信号的边界,为微生物组学研究提供更精确的互作网络分析工具。

weixin_29096377的博客 363

如何优雅地修改同事的代码

在实际的开发过程中,我们很难保证一个业务从头到尾都是自己开发的,我们不得不经常面对修改同事的**代码,本人就因为修改同事的**代码而心烦意乱,直拍桌子,最后被3个领导叫到小办公室训话1小时(是3个领导各训话1小时)。当然,我不是对同事不满,大家都是从最初级的阶段走过来的,他的能力在这个阶段就是这个水准,这是避免不了的。不过工作还要继续,我们要对自己的工作负责任。我只是对自己不满,如果我能找到一种优雅的方式,在不对他的代码进行过多调整的情况下完成需求的开发就好了。

weixin_49015617的博客 1735

企业网络改造必看:如何用华为S5700三层交换机解决多部门隔离通信?

本文详细介绍了如何利用华为S5700三层交换机解决企业多部门网络隔离与通信需求。通过划分VLAN实现逻辑隔离,并配置三层路由实现受控互通,结合ACL进行精细访问控制,构建安全高效的企业网络。文章提供了从拓扑规划、地址分配到核心配置的完整实战指南。

weixin_29260291的博客 262

修改代码技巧(功能迭代、bug修复)

修改代码技巧

Hongwei_1990的博客 2533

构造地貌研究入门:手把手教你用ArcGIS插件CalHypso分析流域地貌形态

本文详细介绍了如何使用ArcGIS插件CalHypso进行流域地貌形态分析,包括工具安装、数据预处理、HI曲线生成及结果解读等关键步骤。通过实战操作,帮助读者掌握面积高程积分(HI)曲线的应用技巧,为构造地貌研究提供量化工具。

weixin_33704234的博客 105

LabVIEW Modbus通讯实战:从安装库到读写寄存器的完整避坑指南

本文详细介绍了LabVIEW与Modbus通讯的完整实战指南,从安装库文件到读写寄存器的全流程操作,帮助开发者避开常见问题。通过虚拟串口配置、主机配置实战和高级调试技巧,提升工业自动化领域的通讯效率与可靠性。

milk8的博客 741

代码的侵入式和非侵入式是什么意思

目录侵入式(引入或继承了别的包或框架)非侵入式(没有依赖,自主研发) 侵入式(引入或继承了别的包或框架) 从字面意思理解,就是你的代码里已经嵌入了别的代码,这些代码可能是你引入过的框架,也可能是你通过接口继承得来的(比如:java中的继承),这样你就可以拥有侵入代码的一些功能。所以我们就称这段代码是侵入式代码。非要说侵入式代码的优点:通过侵入代码与你的代码结合可以更好的利用侵入代码提供给的功能。缺...

RenXiang_Code的博客 2万+

VI4302 1D dToF Sensor助力无人机定高避障:一场前所未有的飞行体验

另外,传感器因测量精度不够,产生的高度信息误差,会导致无人机无法精确定高,影响飞行稳定性和安全降落。芯视界于2022年发布的全新一代基于单光子探测技术的dToF激光雷达传感器芯片-VI4302,采用单电源低功耗系统,实现高性能测距、高稳定性,同时具备极强抗阳光能力以及兼容性等强大优势。无人机可以根据传感器提供的信息,快速调整飞行路径,避开潜在的障碍物,确保平稳的飞行。VI4302 1D dToF Sensor能够以极高的精度测量物体与无人机之间的距离,实现毫米级别的测量精度。⭐ 体型小巧,灵敏度高。

致力于lidar应用开发 624

改两行代码,不动原有结构——最小侵入式改造的一次实践

摘要:本文记录了一次最小侵入式改造的完整实践:在两个Token刷新方法中加入缓存清除逻辑,八处改造点,每处只改一个if结构,原有代码一行不动。文章重点分析了为什么现阶段不抽取公共方法、不优化异常处理——在遗留系统里,决定“不动什么”比决定“改什么”更需要判断力。改造过程中还意外发现了缓存Key粒度冲突的隐患,一举两得。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 846

抖音移动端Web用户主页视频列表爬虫实战:逆向加密参数与高频采集方案

App端Hook/抓包:需要安卓逆向、Xposed或Frida,门槛高且容易被风控。官方开放API:限制极多,几乎不开放用户级视频列表。PC端Web:页面加载方式繁杂,且大量依赖懒加载与内部状态。移动端Web(:接口相对稳定,加密逻辑集中,且适合使用Requests/HTTPSession模拟,无需渲染引擎。本文聚焦于移动端Web下的用户主页视频列表爬取,采用Python 3.11 + httpx + PyExecJS + 正则/JSON解析的组合,破解X-Bogus签名和_signature。

2201_76125261的博客 858

锂电池寿命预测 | Pytorch实现基于Transformer 的锂电池寿命预测(NASA数据集)

锂电池寿命预测 | Pytorch实现基于Transformer 的锂电池寿命预测(NASA数据集)

算法如诗的博客 5588

一种无源代码文件的Java程序修改方法

公司有个老旧项目忽然报错,追踪代码发现逻辑有问题,可又由于公司代码管理不当,导致源码丢失,当前只有可运行的jar包;如果要修复这个问题,只能通过修改字节码文件的方式,然后重新打包部署。

lxmtim的博客 889

【GLM5】手把手教你在openclaw中白嫖英伟达羊毛

openclaw很强,但是也很贵,每一次请求都会消耗大量的token。而英伟达平台正好可以白嫖免费的模型,于是,我们一拍即合。

Science prince的博客 3820

OCP开闭原则

当进行系统功能扩展的时候,如果动了之前稳定的程序,修改了之前的程序,之前所有的程序都需要进行重新测试。这是不想看到的,因为非常麻烦。反之,如果在扩展系统功能的时候,你修改了之前的代码,那么这个设计是失败的,违背OCP原则。只要你在扩展系统功能的时候,没有修改以前写好的代码,那么你就是符合OCP原则。OCP原则是最核心的,最基本的,其他的六个原则都是为这个原则服务的。OCP是软件七大开发原则当中最基本的一个原则:开闭原则。OCP开闭原则的核心是什么?

m0_57484023的博客 195

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring IoC和DI的理解

IoC与DI

Lzfnemo2009的博客 606

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

单一职责原则 & 开闭原则

新增功能:允许扩展新类、新方法,开放扩展​原有代码:不修改、不动原有核心逻辑,关闭修改。

2601_95771059的博客 39

开闭原则(OCP)

基本介绍: 1)开闭原则(OpenClose Principle)是编程中最基础、最重要的设计原则 2)一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节 3)当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。 4)编程中遵循其他原则,以及使用设计模式的目的就是遵循开闭原则。 代码实现; 类图设计如下: package com.atguigu.principle.ocp; pub.

donkeyboy001的博客 366

java设计模式6大设计原则之开闭原则

单一职责原则 1.1 开闭原则定义 在面向对象领域中,开闭原则规定软件中的对象、类、模块和函数对扩展应该是开放的,但对于修改是封闭的。这意味着应该用抽象定义结构,用具体实现扩展细节,以此确保软甲系统的开发和维护过程的稳定性。 开闭原则的核心思想也可以理解为面向抽象编程。 1.2 模拟场景 对于外部调用方来说,只要能体现出面向抽象编程,定义出接口并实现其方法,即不修改原有的方法,之通过继承方式进行扩展,都可以体现出开闭原则。 这里计算三种形状的面积,如长方形、三角形、圆形,它们在类中已经按照固定的公式实现,

Aarstg的博客 337

设计模式--开闭原则

对拓展开放、对修改关闭 有两种理解 模块应该在尽量不修改代码的前提下进行拓展 提供方的变动不会引起使用方的修改 这就指导我们用抽象来构建框架,用实现拓展细节 上一段代码,根据图形代码画图形 class Shape { int type; } /** * 矩形 */ class Rectangle extends Shape { Rectangle() { this.type = 1; } } /** * 这是绘制图形的类 */ class Graphi

lxw389547的博客 187

策略模式结合spring使用优化后的第二版本(符合开闭原则的版本)

前一段时间写一篇策略模式结合spring使用,但是最近发现一点点小问题,就是上次的写法他不符合开闭原则。 开闭原则呢简单来说就是:一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化的(具体的大家可以自行百度) 我们原先的代码呢如下: public class ActionHandlerFactory { private static Map<Byte, ActionHandler> ROUT_MAP; @Autowired private TeacherAct

小菜鸟的博客 225

开放-封闭原则

对扩展开放,对修改关闭。 无论模块是多么的“封闭”,都会存在一些无法对之封闭的变化。等到变化发生时立即采取行动,创建抽象来隔离以后发生的同类变化。比如,实现加法功能,在cilent类中完成的话,以后再加减法操作的时候,就需要修改client类了,就违背了“开闭原则”,这时就需要重构代码,增加一个抽象的运算类,通过继承、多态等来隔离具体的加法、减法与client耦合,需求依然满足,还能应对变化(乘除...

try to do 164

3、抽象工厂模式

package com.yuan; /** * @author QLBF * @version 1.0 * @date 2021/5/24 15:13 */ abstract class TV{ abstract void play(); } class MediaTV extends TV{ @Override void play() { System.out.println("美的电视"); } } class HaierTV extends.

QAQ 163

02 工厂方法模式

原文转载:https://blog.youkuaiyun.com/sinat_21107433/article/details/102616501 在介绍简单工厂方法模式时Jungle总结出简单工厂模式存在最大的问题是违背了“开闭原则”,每当增加新的产品时,需要修改工厂类的逻辑。为了规避这种不足,同时很好的利用简单工厂模式的优点,本节Jungle将声情并茂地为您奉上工厂方法模式。 1.工厂方法模式简介 简单工厂模式中,每新增一个具体产品,就需要修改工厂类内部的判断逻辑。为了不修改工厂类,遵循开闭原则,工厂方法模式

qq_22328661的博客 178

Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例)

Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例) 高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

Java技术加油站的博客 1073

简单工厂

一.什么是简单工厂 简单工厂,由一个工厂对象决定创建出哪一种产品类的实例。它是创建型,但不属于GOF23种设计模式。 工厂类负责创建的对象比较少,客户端(应用层)只知道传入工厂类的参数对于如何创建对象(逻辑)不关心。 简单工厂,只需要传入一个正确的参数,就可以获取所需要的对象而无须知道其创建细节。 但是,工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。 二.代码体现 ...

qq_38844728的博客 164

工厂三兄弟之工厂方法模式(一)

为了突出设计重点,我们对上述代码进行了简化,省略了具体日志记录器类的初始化代码。在图1中,LoggerFactory充当创建日志记录器的工厂,提供了工厂方法createLogger()用于创建日志记录器,Logger是抽象日志记录器接口,其子类为具体日志记录器。(1) 需要封装日志记录器的初始化过程,这些初始化工作较为复杂,例如需要初始化其他相关的类,还有可能需要读取配置文件(例如连接数据库或创建文件),导致代码较长,如果将它们都写在构造函数中,会导致构造函数庞大,不利于代码的修改和维护;

smart_an的专栏 637

设计模式——工厂模式学习总结

至于“运输”如何实现,可以让子公司来实现,也可以让运输工具来实现,都是可以的,但是出于对以后扩展性的考虑,可以让运输工具来实现。比如,我们要将一个系统提供给用户,让用户可以自定义增加运输类型,让用户修改代码,或者让用户写的代码通过我们提供的方式植入到原有的代码中,都可能会带来安全隐患。在没有学习工厂模式前,我是这样想的,分别写个物流公司的类,然后它依赖汽车类和轮船类,让汽车类和轮船都实现运输接口,然后让用户传递一个参数,参数将决定给用户返回汽车或者轮船,这样就实现了。客户可以选择任一运输方式进行运输。

inside802的博客 580
上一篇: 干货!终于有人把设计模式的 “里式替换原则”讲清楚了
下一篇: 十分钟!教你玩转SprintBoot定时任务
大盛玩java
博客等级 码龄5年 0粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值