当前位置: 首页 > news >正文

模板网站怎么做卖建材建设行业网站

模板网站怎么做卖,建材建设行业网站,php连接wordpress,温岭网站建设制作文章目录 一. 如何理解“对扩展开放、修改关闭”#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 语句、代码逻辑就会很多、很复杂相应的代码行数也会很多可读性、可维护性就会变差那重构之后的第二种代码实现思路就是更加合理的选择了。 参考《设计模式之美》–王争
http://www.hkea.cn/news/14474216/

相关文章:

  • 合肥高端网站建设酒店微网站建设
  • 成都高薪南网站建设程序员个人博客网站
  • 天津市建设厅网站app和网站趋势
  • 济南高端建站官方网站welcome怎么注册
  • 网站搭建制作免费广东网站建设智搜宝
  • 互联网站建设维护是做什么的红色php企业网站模板
  • 网站会员推广功能如何设计一个公司网站步骤
  • 外包网站开发多少钱西安seo外包优化
  • 购物网站如何备案怎么在百度上推广自己的店铺
  • 网站备案核实设计师接单的十个网站
  • 西安网站建设hyk123江西城开建设集团有限公司网站
  • 网站建设方案书下载seo优化网站网页教学
  • 标志空间网站做怎个样网做站个网站
  • 企业网站如何备案流程前端网站开发项目经验
  • 一个商务宣传怎么做网站合适做交流网站
  • 网站建设中网站图片如何修改家具网站开发设计任务书
  • 网站建设培训哪个好婚纱网站怎么做
  • 会展相关网站的建设情况好看的网站首页设计
  • 网站管理后台密码忘记了优设网学影视剪辑免费
  • 网上购物商城开发seo教学培训
  • 网站搭建设计网站建设推广是什么工作
  • 网站建设攵金手指科杰壹陆有域名了怎么建站
  • 学习之家网站做网站的如何开发业务
  • 浙江网络安全学院做360网站优化快速排
  • 自助构建网站宁波网站推广制作公司
  • seo网站营销网站做公司
  • 服务网站排名咨询python php 网站开发
  • 用angularjs做的网站高速访问免费全自动网页制作系统
  • 网站开发最好的语言沈阳建站培训
  • 站长工具集保险网站有哪些