海兴县网站建设价格网站开发系统毕业综合实践报告
- 作者: 五速梦信息网
- 时间: 2026年04月20日 11:00
当前位置: 首页 > news >正文
海兴县网站建设价格,网站开发系统毕业综合实践报告,电商公司的网上设计,如何网站专题制作文章目录 一. 如何理解“对扩展开放、修改关闭”#xff1f;二. 修改代码就意味着违背开闭原则吗#xff1f;三. 如何做到“对扩展开放、修改关闭”#xff1f;四. 如何在项目中灵活应用开闭原则#xff1f; 一. 如何理解“对扩展开放、修改关闭”#xff1f; 具体的说二. 修改代码就意味着违背开闭原则吗三. 如何做到“对扩展开放、修改关闭”四. 如何在项目中灵活应用开闭原则 一. 如何理解“对扩展开放、修改关闭” 具体的说添加一个新的功能应该是在已有代码基础上扩展代码新增模块、类、方法等而非修改已有代码修改模块、类、方法等。 举例说明 //业务逻辑主要集中在 check() 函数中。当接口的 TPS 超过某个预先设置的最大值时以及当接口请求出错数大于某个最大允许值时就会触发告警通知接口的相关负责人或者团队。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, …);}} }现在如果我们需要添加一个功能当每秒钟接口超时请求个数超过某个预先设置的最大阈值时我们也要触发告警发送通知。 通过修改已有代码来实现 //- 第一处是修改 check() 函数的入参添加一个新的统计数据 timeoutCount表示超时接口请求数 //- 第二处是在 check() 函数中添加新的告警逻辑。 public class Alert { …// 改动一添加参数timeoutCountpublic void check(String api, long requestCount, long errorCount, long timeoutCount, 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, …);}// 改动二添加接口超时处理逻辑long timeoutTps timeoutCount / durationOfSeconds;if (timeoutTps rule.getMatchedRule(api).getMaxTimeoutTps()) {notification.notify(NotificationEmergencyLevel.URGENCY, …);}} }这样的代码修改实际上存在挺多问题的。 一方面我们对接口进行了修改这就意味着调用这个接口的代码都要做相应的修改。另一方面修改了 check() 函数相应的单元测试都需要修改关于单元测试的内容我们在重构那部分会详细介绍。 通过“扩展”的方式来实现同样的功能 先重构一下之前的 Alert 代码让它的扩展性更好一些。 重构一将 check() 的入参封装到 ApiStatInfo 类重构二引入 handler 的概念将 if 判断逻辑分散在各个 handler 中。 public class Alert {private ListAlertHandler alertHandlers new ArrayList();public void addAlertHandler(AlertHandler alertHandler) {this.alertHandlers.add(alertHandler);} //封装入参public void check(ApiStatInfo apiStatInfo) {for (AlertHandler handler : alertHandlers) {handler.check(apiStatInfo);}} }public class ApiStatInfo {//省略constructor/getter/setter方法private String api;private long requestCount;private long errorCount;private long durationOfSeconds; }//2. 添加handler抽象类定义公共属性和方法 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, …);}} }在重构之后的代码中实现新的需求有如下改动 在 ApiStatInfo 类中添加新的属性 timeoutCount。添加新的 TimeoutAlertHander 类。在 ApplicationContext 类的 initializeBeans() 方法中往 alert 对象中注册新的 timeoutAlertHandler。在使用 Alert 类的时候需要给 check() 函数的入参 apiStatInfo 对象设置 timeoutCount 的值。 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));// 改动三注册handleralert.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); }重构之后的代码更加灵活和易扩展。 如果我们要想添加新的告警逻辑只需要基于扩展的方式创建新的 handler 类即可不需要改动原来的 check() 函数的逻辑。而且我们只需要为新的 handler 类添加单元测试老的单元测试都不会失败也不用修改。 二. 修改代码就意味着违背开闭原则吗 看了上面重构之后的代码你可能还会有疑问在添加新的告警逻辑的时候尽管改动二添加新的 handler 类是基于扩展而非修改的方式来完成的但改动一、三、四貌似不是基于扩展而是基于修改的方式来完成的那改动一、三、四不就违背了开闭原则吗 我们回到这条原则的设计初衷只要它没有破坏原有的代码的正常运行没有破坏原有的单元测试我们就可以说这是一个合格的代码改动。 分析一下改动三和改动四这两处改动都是在方法内部进行的不管从哪个层面模块、类、方法来讲都不能算是“扩展”而是地地道道的“修改”。不过有些修改是在所难免的是可以被接受的。 如果我们把 Alert 类及各个 handler 类合起来看作一个“模块”那模块本身在添加新的功能的时候完全满足开闭原则。 要认识到添加一个新功能不可能任何模块、类、方法的代码都不“修改”这个是做不到的。类需要创建、组装、并且做一些初始化操作才能构建成可运行的的程序这部分代码的修改是在所难免的。 我们要做的是尽量让修改操作更集中、更少、更上层尽量让最核心、最复杂的那部分逻辑代码满足开闭原则。 三. 如何做到“对扩展开放、修改关闭” 实际上开闭原则讲的就是代码的扩展性问题是判断一段代码是否易扩展的“金标准”。如果某段代码在应对未来需求变化的时候能够做到“对扩展开放、对修改关闭”那就说明这段代码的扩展性比较好。 所以问如何才能做到“对扩展开放、对修改关闭”也就粗略地等同于在问如何才能写出扩展性好的代码。 在讲具体的方法论之前我们先来看一些更加偏向顶层的指导思想。为了尽量写出扩展性好的代码我们要具备扩展意识、抽象意识、封装意识。 支持开闭原则的一些更加具体的方法论。 在众多的设计原则、思想、模式中最常用来提高代码扩展性的方法有多态、依赖注入、基于接口而非实现编程以及大部分的设计模式比如装饰、策略、模板、职责链、状态等。 如何利用多态、依赖注入、基于接口而非实现编程来实现“对扩展开放、对修改关闭”。 比如我们代码中通过 Kafka 来发送异步消息。对于这样一个功能的开发我们要学会将其抽象成一组跟具体消息队列Kafka无关的异步消息接口。 所有上层系统都依赖这组抽象的接口编程并且通过依赖注入的方式来调用。 当我们要替换新的消息队列的时候比如将 Kafka 替换成 RocketMQ可以很方便地拔掉老的消息队列实现插入新的消息队列实现。具体代码如下所示 // 这一部分体现了抽象意识 public interface MessageQueue { //… } public class KafkaMessageQueue implements MessageQueue { //… } public class RocketMQMessageQueue implements MessageQueue {//…}public interface MessageFromatter { //… } public class JsonMessageFromatter implements MessageFromatter {//…} public class ProtoBufMessageFromatter implements MessageFromatter {//…}public class Demo {private MessageQueue msgQueue; // 基于接口而非实现编程public Demo(MessageQueue msgQueue) { // 依赖注入this.msgQueue msgQueue;}// msgFormatter多态、依赖注入public void sendNotification(Notification notification, MessageFormatter msgFormatter) {//… } }四. 如何在项目中灵活应用开闭原则 前面我们提到写出支持“对扩展开放、对修改关闭”的代码的关键是预留扩展点。那问题是如何才能识别出所有可能的扩展点呢 最合理的做法 对于一些比较确定的、短期内可能就会扩展或者需求改动对代码结构影响比较大的情况或者实现成本不高的扩展点在编写代码的时候之后我们就可以事先做些扩展性设计。对于一些不确定未来是否要支持的需求或者实现起来比较复杂的扩展点我们可以等到有需求驱动的时候再通过重构代码的方式来支持扩展的需求。 开闭原则增加了理解难度 我们之前举的 Alert 告警的例子。为了更好地支持扩展性我们对代码进行了重构重构之后的代码要比之前的代码复杂很多理解起来也更加有难度。 需要在扩展性和可读性之间做权衡 在某些场景下代码的扩展性很重要我们就可以适当地牺牲一些代码的可读性在另一些场景下代码的可读性更加重要那我们就适当地牺牲一些代码的可扩展性。 在 Alert 告警的例子中如果告警规则并不是很多、也不复杂那 check() 函数中的 if 语句就不会很多代码逻辑也不复杂代码行数也不多那最初的第一种代码实现思路简单易读就是比较合理的选择。 相反如果告警规则很多、很复杂check() 函数的 if 语句、代码逻辑就会很多、很复杂相应的代码行数也会很多可读性、可维护性就会变差那重构之后的第二种代码实现思路就是更加合理的选择了。 参考《设计模式之美》–王争
- 上一篇: 海外直购网站建设方案书范文北京网站建设公司大全
- 下一篇: 海晏网站制作建筑网站建设赏析
相关文章
-
海外直购网站建设方案书范文北京网站建设公司大全
海外直购网站建设方案书范文北京网站建设公司大全
- 技术栈
- 2026年04月20日
-
海外营销网站中山医疗网站建设
海外营销网站中山医疗网站建设
- 技术栈
- 2026年04月20日
-
海外网站制作wordpress开启多站点好处
海外网站制作wordpress开启多站点好处
- 技术栈
- 2026年04月20日
-
海晏网站制作建筑网站建设赏析
海晏网站制作建筑网站建设赏析
- 技术栈
- 2026年04月20日
-
海洋高端的专业做网站html做电商网站
海洋高端的专业做网站html做电商网站
- 技术栈
- 2026年04月20日
-
海洋公园网站建设方案苏州市吴中区住房和城乡建设局官方网站
海洋公园网站建设方案苏州市吴中区住房和城乡建设局官方网站
- 技术栈
- 2026年04月20日
