整洁架构SOLID-开闭原则(OCP)

文章目录

  • 1 定义
  • 2 最佳实践
    • 2.1 需求
    • 2.2 需求变更
    • 2.3 变更原则
    • 2.4 实现逻辑
      • 2.4.1 组件化
      • 2.4.2 组件关系
    • 2.5 依赖方向的控制
  • 3 本章小结

1 定义

开闭原则(OCP)是Bertrand Meyer在1988年提出的,该设计原则认为:

设计良好的计算机软件应该易于扩展,同时抗拒修改。

换句话说,一个设计良好的计算机系统应该在不需要修改的前提下就可以轻易被扩展

如果对原始需求的小小延伸就需要对原有的软件系统进行大幅修改,那么这个系统的架构设计显然是失败的。在软件架构层面,这项原则的意义重大。

2 最佳实践

2.1 需求

我们现在要设计一个在Web页面上展示财务数据的系统,页面上的数据要可以滚动显示,其中负值应显示为红色。

2.2 需求变更

接下来,该系统的所有者又要求同样的数据需要形成一个报表,该报表要能用黑白打印机打印,并且其报表格式要得到合理分页,每页都要包含页头、页尾及栏目名。同时,负值应该以括号表示。

2.3 变更原则

显然,我们需要增加一些代码来完成这个要求。但在这里我们更关注的问题是,满足新的要求需要更改多少旧代码

2.4 实现逻辑

2.4.1 组件化

但该如何实现这一点呢?我们可以先将满足不同需求的代码分组(即SRP),然后再来调整这些分组之间的依赖关系(即DIP)。

利用SRP,我们可以按图中所展示的方式来处理数据流。即先用一段分析程序处理原始的财务数据,以形成报表的数据结构,最后再用两个不同的报表生成器来产生报表。
在这里插入图片描述

这里的核心就是将应用生成报表的过程拆成两个不同的操作。即先计算出报表数据,再生成具体的展示报表(分别以网页及纸质的形式展示)。

2.4.2 组件关系

接下来,我们就该修改其源代码之间的依赖关系了。这样做的目的是保证其中一个操作被修改之后不会影响到另外一个操作。同时,我们所构建的新的组织形式应该保证该程序后续在行为上的扩展都无须修改现有代码

在具体实现上,我们会将整个程序进程划分成一系列的类,然后再将这些类分割成不同的组件。下面,我们用下图中的那些双线框来具体描述一下整个实现。在这个图中,左上角的组件是Controller,右上角是Interactor,右下角是Database,左下角则有四个组件分别用于代表不同的Presenter和View。在下图中,用<I>标记的类代表接口,用<DS>标记的则代表数据结构;开放箭头指代的是使用关系,闭合箭头则指代了实现与继承关系。

下图中看到的所有依赖关系都是其源代码中存在的依赖关系。这里,从类A指向类B的箭头意味着A的源代码中涉及了B,但是B的源代码中并不涉及A。因此在下图中,FinancialDataMapper在实现接口时需要知道FinancialDataGateway的实现,而FinancialDataGateway则完全不必知道FinancialDataMapper的实现。
在这里插入图片描述

这里很重要的一点是这些双线框的边界都是单向跨越的。也就是说,上图中所有组件之间的关系都是单向依赖的,如上图所示,图中的箭头都指向那些我们不想经常更改的组件

让我们再来复述一下这里的设计原则:

如果A组件不想被B组件上发生的修改所影响,那么就应该让B组件依赖于A组件

所以我们不想让发生在Presenter上的修改影响到Controller,也不想让发生在View上的修改影响到Presenter。而最关键的是,我们不想让任何修改影响到Interactor。

其中,Interactor组件是整个系统中最符合OCP的。发生在Database、Controller、Presenter甚至View上的修改都不会影响到Interactor。
在这里插入图片描述

为什么Interactor会被放在这么重要的位置上呢?因为它是该程序的业务逻辑所在之处,Interactor中包含了其最高层次的应用策略。其他组件都只是负责处理周边的辅助逻辑,只有Interactor才是核心组件。

虽然Controller组件只是Interactor的附属品,但它却是Presenter和View所服务的核心。同样的,虽然Presenter组件是Controller的附属品,但它却是View所服务的核心。

这里利用“层级”这个概念创造了一系列不同的保护层级。譬如,Interactor是最高层的抽象,所以它被保护得最严密,而Presenter比View的层级高,但比Controller和Interactor的层级低。

以上就是我们在软件架构层次上对OCP这一设计原则的应用。软件架构师可以根据相关函数被修改的原因、修改的方式及修改的时间来对其进行分组隔离,并将这些互相隔离的函数分组整理成组件结构,使得高阶组件不会因低阶组件被修改而受到影响。

2.5 依赖方向的控制

刚刚在图中所看到的复杂度是我们想要对组件之间的依赖方向进行控制而产生的。

例如,FinancialReportGenerator和FinancialDataMapper之间的FinancialDataGateway接口是为了反转Interactor与Database之间的依赖关系而产生的。同样的,FinancialReportPresenter接口与两个View接口之间也类似于这种情况。

FinancialReportRequester接口的作用则完全不同,它的作用是保护FinancialReportController不过度依赖于Interactor的内部细节。如果没有这个接口,则Controller将会传递性地依赖于FinancialEntities。

这种传递性依赖违反了“软件系统不应该依赖其不直接使用的组件”这一基本原则。

虽然我们的首要目的是为了让Interactor屏蔽掉发生在Controller上的修改,但也需要通过隐藏Interactor内部细节的方法来让其屏蔽掉来自Controller的依赖。

3 本章小结

OCP是我们进行系统架构设计的主导原则,其主要目标是让系统易于扩展,同时限制其每次被修改所影响的范围。实现方式是通过将系统划分为一系列组件,并且将这些组件间的依赖关系按层次结构进行组织,使得高阶组件不会因低阶组件被修改而受到影响。

参考内容来源于:《架构整洁之道》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/780014.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

认识并理解webSocket

今天逛牛客,看到有大佬分享说前端面试的时候遇到了关于webSocket的问题,一看自己都没见过这个知识点,赶紧学习一下,在此记录! WebSocket 是一种网络通信协议,提供了全双工通信渠道,即客户端和服…

Unity3D游戏 RPG

丛林探险游戏 人物进行探险游戏 拥有登录,首页,3D物体旋转浏览的功能,还能进行种植树等功能

GD32 MCU ADC采样率如何计算?

大家在使用ADC采样的时候是否计算过ADC的采样率,这个问题非常关键! 以下为GD32F303系列MCU中有关ADC的参数,其中ADC时钟最大值为40MHz,12位分辨率下最大采样率为2.86MSPS.如果ADC时钟超频的话,可能会造成ADC采样异常&…

【总线】AXI4第七课时:AXI的额外的控制信息(PROT和CACHE)

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣,那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者,AXI4以其高性能和高度可扩展性,成为了现代电子系统中不可或缺的通信桥梁…

Vue3.js“非原始值”响应式实现基本原理笔记(二)

如果您觉得这篇文章有帮助的话!给个点赞和评论支持下吧,感谢~ 作者:前端小王hs 阿里云社区博客专家/清华大学出版社签约作者/csdn百万访问前端博主/B站千粉前端up主 此篇文章是博主于2022年学习《Vue.js设计与实现》时的笔记整理而来 书籍&a…

STM32F103C8T6核心板原理图和PCB分享

PCB图 原理图 资料下载地址: 原理图PCB库: https://545c.com/d/45573183-61875742-29897c?p7526 (访问密码: 7526)

第3章.中央服务器的物联网模式--企业系统集成

为了从物联网实施中获得最大价值,物联网系统需要与企业中的现有软件系统集成。事实上,与外部系统的集成允许网络世界和物理世界之间的交互——代表物理世界的物联网系统和驻留在网络/虚拟世界中的外部系统。用于此模式的符号如下图所示: 图3.…

mac怎么压缩pdf文件大小,mac压缩pdf文件大小不改变清晰度

在数字化时代,pdf格式因其良好的兼容性和稳定性,成为了文档分享和传输的首选。然而,随着文件内容的丰富,pdf文件的体积也越来越大,给存储和传输带来了不小的困扰。本文将揭秘几种简单有效的pdf文件压缩方法&#xff0c…

图神经网络实战(16)——经典图生成算法

图神经网络实战(16)——经典图生成算法 0. 前言1. 图生成技术2. Erdős–Rnyi模型3. 小世界模型小结系列链接 0. 前言 图生成算法是指用于创建模拟图或网络结构的算法,这些算法可以根据特定的规则和概率分布生成具有特定属性的图&#xff0c…

SCI一区级 | Matlab实现BO-Transformer-BiLSTM时间序列预测

SCI一区级 | Matlab实现BO-Transformer-BiLSTM时间序列预测 目录 SCI一区级 | Matlab实现BO-Transformer-BiLSTM时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【SCI一区级】Matlab实现BO-Transformer-BiLSTM时间序列预测,贝叶斯优化Transfor…

C++_STL---list

list的相关介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 list的底层是带头双向循环链表结构,链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。…

WAIC | 上海人形机器人创新中心 | 最新演讲 | 详细整理

前言 笔者看了7月4号的人形机器人与具身智能发展论坛的直播,并在7月5日到了上海WAIC展会现场参观。这次大会的举办很有意义,听并看了各家的最新成果,拍了很多照片视频,部分演讲也录屏了在重复观看学习 稍后会相继整理创立穹彻智…

[c++] 可变参数模版

前言 可变参数模板是C11及之后才开始使用,学校的老古董编译器不一定能用 相信大家在刚入门c/c时都接触过printf函数 int printf ( const char * format, ... ); printf用于将数据格式化输出到屏幕上,它的参数非常有意思,可以支持任意数量,任意类型的多参数.而如果我们想实现类…

【Java探索之旅】继承概念_语法_父类的成员访问

文章目录 📑前言一、继承1.1 继承的概念1.2 继承语法1.3 继承发生后 二、父类的访问2.1 父类成员变量访问2.2 父类成员方法访问 🌤️全篇总结 📑前言 在面向对象编程中,继承是一种重要的概念,它允许我们创建一个类&…

[go-zero] 简单微服务调用

文章目录 1.注意事项2.服务划分及创建2.1 用户微服务2.2 订单微服务 3.启动服务3.1 etcd 服务启动3.2 微服务启动3.3 测试访问 1.注意事项 go-zero微服务的注册中心默认使用的是Etcd。 本小节将以一个订单服务调用用户服务来简单演示一下,其实订单服务是api服务&a…

VSCode设置好看清晰的字体!中文用鸿蒙,英文用Jetbrains Mono

一、中文字体——HarmonyOS Sans SC 1、下载字体 官网地址:https://developer.huawei.com/consumer/cn/design/resource/ 直接下载:https://communityfile-drcn.op.dbankcloud.cn/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20230517…

昇思25天学习打卡营第18天 | K近邻算法实现红酒聚类

1、实验目的 了解KNN的基本概念;了解如何使用MindSpore进行KNN实验。 2、K近邻算法原理介绍 K近邻算法(K-Nearest-Neighbor, KNN)是一种用于分类和回归的非参数统计方法,最初由 Cover和Hart于1968年提出(Cover等人,1967)&#…

Golang | Leetcode Golang题解之第220题存在重复元素III

题目: 题解: func getID(x, w int) int {if x > 0 {return x / w}return (x1)/w - 1 }func containsNearbyAlmostDuplicate(nums []int, k, t int) bool {mp : map[int]int{}for i, x : range nums {id : getID(x, t1)if _, has : mp[id]; has {retu…

ctfshow web sql注入 web242--web249

web242 into outfile 的使用 SELECT ... INTO OUTFILE file_name[CHARACTER SET charset_name][export_options]export_options:[{FIELDS | COLUMNS}[TERMINATED BY string]//分隔符[[OPTIONALLY] ENCLOSED BY char][ESCAPED BY char]][LINES[STARTING BY string][TERMINATED…

【三级等保】等保整体建设方案(Word原件)

建设要点目录: 1、系统定级与安全域 2、实施方案设计 3、安全防护体系建设规划 软件全文档,全方案获取方式:本文末个人名片直接获取。