设计模式学习[3]---单一职责原则+开放封闭原则

文章目录

  • 前言
  • 1. 单一职责
    • 1.1 原理阐述
    • 1.2 处理方式
  • 2. 开放-封闭原则
    • 2.1 原理阐释
    • 2.2 举例说明
  • 总结

前言

小项目写多了,比如一些什么管理系统之类的,在接触大型项目的时候往往会将之前的一些面向过程的写法代入。
比如UI以及逻辑处理都放在一个类里面,UI里面加什么,我这个类里面加什么,改什么。代码改多了之后,对于新的需求,有很大概率需要重构代码,因为要处理的地方太多了。
软件讲究高内聚,低耦合,便于拓展,模块化。之前这些存在于书本上的概念,在实际开发中,是真真切切的用得上的。

对于上面的情况,这篇博客写一下处理方式。

1. 单一职责

首先是前言提到的UI以及逻辑都放在一个类里面处理这种情况。

借用书的例子做一个衍生。
目前手机拍照的效果和十年前的单反来比,效果差距还是很明显。
手机复合的功能太多,拍照,打电话,玩游戏等等,总共的空间就那么大,既要又要,所以就要对各个功能做一些取舍。常常是每一个功能都没有那么专业,仅能符合大众的日常使用需求。从照相这个功能来说,手机就不算是专业的了。
而单反相机,无论是CMOS还是性能上比手机好的太多,相机的作用在照相这个功能点上发挥到了极致。其他的点就不行了,相机打不了游戏,打不了电话…

那么在我UI和逻辑处理这个合成类中来说,它的职责就和手机一样,既要又要,导致软件在某个功能点并不拔尖。要想让这个类的作用发挥到最大,那就要使其专一化,也就是职责的单一化。


1.1 原理阐述

单一职责原则:就一个类而言,应该仅有一个引起它变化的原因

我们在做编程的时候,很自然地就会给一个类加各种各样的功能,比如我们写一个窗体应用程序,一般都会生成一个 F o r m 1 Form1 Form1这样的类,于是我们就把各种各样的代码,像某种商业运算的算法呀,像数据库访问的 S Q L SQL SQL语句呀什么的都写到这样的类当中,这就意味着,无论任何需求要来,你都需要更改这个窗体类,这其实是很糟糕的,维护麻烦,复用不可能,也缺乏灵活性。

1.2 处理方式

刚才讲了那么多,无非就是一个核心点。
一个类,做一个功能。
对于UI和一些业务代码,我们要做的就是把 U I UI UI用一个类来管理操作,把业务代码用另一个类进行封装。
UI中要处理业务的地方,调用对应类的接口即可。实际处理业务不在UI类就可以了。

如果要用算法,我们可以给算法封装个类。业务处理如果要用算法,我们直接调用算法类就可以了,而不是把算法写在业务处理中。


2. 开放-封闭原则

前言部分我提到:软件讲究高内聚,低耦合,便于拓展,模块化。

我们在做任何系统的时候,都不要指望系统一开始时需求确定,就再也不会变化,这是不现实也不科学的想法,而既然需求是一定会变化的,那么如何在面对需求的变化时,设计的软件可以相对容易修改,不至于说,新需求一来,就要把整个程序推倒重来。怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢?开放-封闭给我们答案。

2.1 原理阐释

这个原则其实是有两个特征,对于扩展是开放的(Open for extension) ,另一个是对于更改是封闭的(Closed for modification)

我的理解是,我已有的软件,如果要添加功能,那么欢迎添加功能,但是我已有的功能你不能动。添加功能就只管添加功能,如果要更改功能,那是别的类的事情。

这就要求我们设计的时候,时刻要考虑,尽量让这个类是足够好,写好了就不要去修改了,如果新需求来,我们增加一些类就完事了,原来的代码能不动则不动。

不过,我们是很难预先猜测,但我们却可以在发生小变化时,就及早去想办法应对发生更大变化的可能。也就是说,等到变化发生时立即采取行动。


2.2 举例说明

在我们最初编写代码时,假设变化不会发生。
当变化发生时,我们就创建抽象来隔离以后发生的同类变化。

比如,加法程序,我们可以很快在一个client类中就完成,此时变化还没有发生。然后再加一个减法功能,你发现,增加功能需要修改原来这个类,这就违背了‘开放-封闭原则’,于是就该考虑重构程序,增加一个抽象的运算类,通过一些面向对象的手段,如继承,多态等来隔离具体加法、减法与client耦合,需求依然可以满足,还能应对变化。这时又要再加乘除法功能,你就不需要再去更改client以及加法减法的类了,而是增加乘法和除法子类就可。
即面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。

在这里插入图片描述


总结

单一职责模式以及开放封闭原则,其实很大程度上不能做到完全遵守。就像我近期在公司的框架下开发新功能,有些地方不得不让一个类对某些功能进行耦合,不能完全做到单一职责。这是因为这个类在以前的代码中牵扯到很多其他代码,如果要完全实现,就必须重构,费时费力。开放封闭也是一样的道理。

这篇博客的两篇原则,总的来说是在我们开发的时候,尤其是在写新类的时候需要着重关注的。实在实现不了百分百的效果,我们亦可以通过遵守设计原则,方便后面的拓展与优化。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter【01】状态管理

声明式编程 Flutter 应用是 声明式 的,这也就意味着 Flutter 构建的用户界面就是应用的当前状态。 当你的 Flutter 应用的状态发生改变时(例如,用户在设置界面中点击了一个开关选项)你改变了状态,这将会触发用户界面…

25届科大讯飞飞星计划 AI研究算法工程师 面经

目录 一面/技术面 2024/08/15 📋 总结: 本来应该是在7月底面试的,但因为有事就拖到了现在,或许是飞星计划里最晚面试的一批?面试官很和蔼,问的问题不算难,总体体验还算不错。 一面/技术面 2024/…

洛谷B3981题解

题目描述 (你不需要看懂这张图片;但如果你看懂了,会觉得它很有趣。) JavaScript 是一种功能强大且灵活的编程语言,也是现代 Web 开发的三大支柱之一 (另外两个是 HTML 和 CSS)。灵活的 JavaScript 包含“自动类型转换…

Python 数据分析之Numpy学习(一)

Python 数据分析之Numpy学习(一) 一、Numpy的引入 1.1 矩阵/向量的按位运算 需求:矩阵的按位相加 [0,1,4] [0,1,8] [0,2,12] 1.1.1 利用python实现矩阵/向量的按位运算 # 1.通过列表实现 list1 [0, 1, 4] list2 [0, 1, 8]# 列表使用…

【Linux网络】select函数

欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 select函数介绍select函数参数介绍select函数返回值select的工作流程TCP服务器【多路复用版】 select函数介绍 在Linux网络编程中,select 函数是一种非常有用的IO多路复用技术&#xff0…

基于Java和GeoTools的Shapefile矢量数据缩略图生成实践

目录 前言 一、关于GeoTools的图片生成 1、关于GtRenderer 2、关于 图像生成架构 3、流式计算绘制 二、全球空间预览生成实战 1、pom.xml中关于图像生成依赖 2、样式设置及地图资源绑定 3、图片生成绘制 4、图片生成测试 三、成果验证 1、全球范围生成 2、我国的范…

redis随笔记

缓存穿透。key不存在。恶意攻击、代码问题。加布隆过滤器,或者为空就返回。 缓存失效(击穿)。key刚好过期。缓存时间随机数。 缓存雪崩。缓存层宕机,一下子袭击数据库。缓存高可用、限流熔断、提前演练。 布隆过滤器就是一个key…

Python版《超级玛丽+源码》-Python制作超级玛丽游戏

小时候最喜欢玩的小游戏就是超级玛丽了,有刺激有又技巧,通关真的很难,救下小公主还被抓走了,唉,心累,最后还是硬着头皮继续闯,终于要通关了,之后再玩还是没有那么容易,哈…

从并发20到并发120之laravel性能优化

调优成果 遇到问题 单台服务并发20,平均响应时间1124ms,通过htop观察,发现cpu占用率达到100%(包括sleep的进程),内存几乎没怎么用。 调优后 单机最大吞吐量达到120 响应时长不超过1000ms 硬件信息 …

EfficientFormer 系列算法

1. EfficientFormer V1 模型 论文地址:https://proceedings.neurips.cc/paper_files/paper/2022/file/5452ad8ee6ea6e7dc41db1cbd31ba0b8-Paper-Conference.pdf EfficientFormer V1 基于 ViT 的模型中使用的网络架构和具体的算子,找到端侧低效的原因。然…

高性能web服务器nginx

目录 nginx简介 服务端 I/O 流程 Nginx 进程结构 Nginx启动流程 nginx的源码编译下载 nginx命令常见参数 nginx的配置文件详解 全局配置优化 nginx的平滑升级和回滚 nginx目录匹配优先级测试(因为只支持访问文件,所有不比对匹配目录优先级&…

五、2 移位操作符赋值操作符

1、移位操作符 2、赋值操作符 “ ”赋值,“ ”判断是否相等 1)连续赋值 2)复合赋值符

C ++初阶:类和对象(上)

目录 🌞0.前言 1. 面向过程和面向对象初步认识 2..类的引入与定义 2.1类的引入 2.2类的定义 3.类的访问限定符及其封装 3.1访问限定符 3.2封装 4.类的作用域 4.1加餐和发现 5.类的实例化 6.类对象大小的计算 6.1.内部的存储方式 6.2结构体对齐规则回顾…

一、什么是 mvvm? MVC、MVP、MVVM三种模式的区别与详解

简介 MVC、MVP、MVVM都是常见的软件架构模式。 MVC(Model-View-Controller)架构模式中,将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller&…

STM32自制手持小风扇实验

1.1 介绍: 实验功能说明:功能(1)按一下按键小风扇开启,再按一下关闭。 功能(2)按一下按键小风扇一档风速,再按一下二挡,依次三挡…关闭。 按键模块说明:按下…

什么是AR、VR、MR、XR?

时代背景 近年来随着计算机图形学、显示技术等的发展,视觉虚拟化技术得到了广泛的发展,并且越来越普及化,慢慢的也走入人们的视野。目前市场上视觉虚拟化技术的主流分为这几种 VR、AR、MR、XR。这几项技术并不是最近才出现的,VR的…

路由器VLAN配置(H3C)

路由器VLAN配置(H3C) 控制页面访问 路由器默认处于192.168.1.1网段(可以短按reset重置),如果要直接使用需要设置静态IP处于同一网段; 对路由器进行配置也要将电脑IP手动设置为同一网段; 默…

执行rasa shell 遇到asyncio.exceptions.TimeoutError报错

在《树莓派3B运行rasa init和rasa shell遇到的tensorflow报错总结》一文中,我遇到的第7个报错是首次运行rasa shell时候碰到的。按照我在文中记录的解决方案,处理成功。 结果,今天我又一次遇到了asyncio - Task exception was never retrie…

91. 解码方法 -dp4

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/decode-ways/description/ 示例 1: 输入:s &…