软件设计原则之单一职责原则

news2024/9/20 18:33:21

目录

  • 单一职责原则
  • 单一职责原则的主要特点
  • 应用范围
  • Demo
    • 用户信息
    • 日志记录

单一职责原则

单一职责原则(Single Responsibility Principle,简称SRP)是面向对象设计中的一个重要原则,其核心思想是:一个类应该仅有一个引起它变化的原因。换句话说,一个类应该负责一组相对独立且内聚的职责。当这个类需要承担更多的职责时,就应该考虑将其拆分为多个类,每个类负责一个单一的职责。

单一职责原则的主要特点

清晰性: 遵循单一职责原则可以让代码结构更加清晰,每个类或模块只负责完成一项任务,使得代码更容易理解和维护。
低耦合: 当一个类承担的职责过多时,它与其他类的交互就会变得更加复杂,从而增加了系统的耦合度。遵循单一职责原则,可以使得类与类之间的依赖关系更加清晰,降低耦合度。
高内聚: 遵循单一职责原则的类通常具有较高的内聚性,即类内的元素之间联系紧密,共同为完成一个职责而努力。
可维护性: 当系统需要修改或扩展时,如果类的职责单一,那么修改的影响范围就会相对较小,从而更容易维护。
可读性: 类的职责明确,使得代码更加易于理解和阅读。其他开发者在查看代码时,可以更快地理解类的功能和作用。
灵活性: 由于类的职责单一,因此可以更容易地对其进行重构或替换,以适应新的需求或技术变化。
如何应用单一职责原则
识别职责: 首先,需要仔细分析类的职责,明确它应该做什么。这通常需要对系统的需求有深入的理解。
划分职责: 如果发现一个类承担了多个职责,那么应该考虑将这些职责划分到不同的类中。每个类只负责一个职责,并且这个职责应该是相对独立且内聚的。
重构代码: 根据职责的划分,对代码进行重构。将原有的类拆分为多个类,每个类只包含与其职责相关的属性和方法。
持续审查: 随着系统的不断发展和变化,类的职责也可能会发生变化。因此,需要持续审查类的职责,确保它们仍然符合单一职责原则。

应用范围

接口、类、方法。
SRP应用到方法中,每个方法的职责明确清晰。接口一定要做到单一职责,类的的设计尽量做到单一职责。
类设计: 最直接的应用就是在类的设计上。一个类应该只负责一组相对独立的功能或行为。如果一个类承担的职责过多,就应该考虑将其拆分成多个类,每个类负责一个具体的职责。
接口设计: 接口也应该遵循单一职责原则。一个接口应该只定义一组相关的方法,这些方法应该属于同一职责范畴。如果接口中的方法职责差异较大,应该考虑将其拆分成多个接口。
模块设计: 在更大的层面上,单一职责原则也适用于模块设计。一个模块应该只负责一组相关的功能,避免模块之间职责的重叠和混淆。
服务设计: 在微服务架构中,单一职责原则同样重要。每个微服务应该只负责一个独立的业务功能或领域,确保服务的内聚性和独立性。
方法设计:虽然单一职责原则主要针对类和接口,但方法的设计也应该尽量遵循这一原则。一个方法应该只完成一个明确的任务,避免在方法内部执行多个不相关的操作。
数据库设计: 在数据库设计中,单一职责原则也具有一定的指导意义。例如,表的设计应该遵循单一职责原则,一个表应该只存储与某一业务实体相关的数据,避免表中包含多个业务实体的混合数据。
组件设计: 在组件化开发中,每个组件也应该只负责一个具体的职责。组件之间应该通过清晰的接口进行交互,避免组件内部职责的混乱和交叉。

Demo

用户信息

假设我们有一个User类,它同时负责用户信息的存储和用户登录验证。这明显违反了单一职责原则,因为存储信息和登录验证是两个相对独立的职责。

// 存储用户信息  
public class UserInfo {  
    private String username;  
    private String password;  
  
    // 存储用户信息  
    public void saveUserInfo() {  
        // 实现存储逻辑  
    }  
}  
  
// 用户登录验证  
public class UserAuthenticator {  
    private UserInfo userInfo;  
  
    public UserAuthenticator(UserInfo userInfo) {  
        this.userInfo = userInfo;  
    }  
  
    // 用户登录验证  
    public boolean validateLogin(String inputUsername, String inputPassword) {  
        return userInfo.getUsername().equals(inputUsername) && userInfo.getPassword().equals(inputPassword);  
    }  
}

日志记录

class FileLogger {
    public void log(String message) {
        // 将日志写入文件
    }
}class DatabaseLogger {
    public void log(String message) {
        // 将日志存入数据库
    }
}class LogManager {
    private FileLogger fileLogger;
    private DatabaseLogger databaseLogger;public LogManager(FileLogger fileLogger, DatabaseLogger databaseLogger) {
        this.fileLogger = fileLogger;
        this.databaseLogger = databaseLogger;
    }public void logToFile(String message) {
        fileLogger.log(message);
    }public void logToDatabase(String message) {
        databaseLogger.log(message);
    }
}

通过这样的拆分,我们使得每个类的职责更加明确,也更容易进行维护和扩展。
虽然单一职责原则很重要,但也要注意避免过度设计。过度遵循单一职责原则可能会导致系统中的类过多、依赖关系复杂,反而增加系统的复杂性和维护成本。因此,在应用单一职责原则时,需要权衡利弊,确保设计的合理性和可行性。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ollma 本地部署大模型

因为我本地是 windows 的系统,所以这里直接写的是通过 docker 来实现本地大模型的部署。 windows 下 WSl 的安装这里就不做重复,详见 windows 部署 mindspore GPU 开发环境(WSL) 一、Docker 部署 ollma 1. 拉取镜像(…

Ubuntu系统设置Java项目开机自启

1、创建自启动脚 sudo vi /etc/systemd/system/java-service.service 2、编辑自启脚本 [Unit]部分包含了service的描述和依赖关系。在这个示例中,我们将其设置为在系统启动后执行。 [Service]部分定义了service的执行方式。在这个示例中,我们指定了Java…

shell工具箱集合!!

shell工具箱集合 1.shell工具箱集合 2.Chrony 时间同步 3.Get_host_Info 设备信息收集 4.Init_host 系统初始化 5.Iperf 带宽测试套件 6.Lagscope_test 时延测试套件 7.Mtr_test 双向路由探测套件 下载地址: https://pan.quark.cn/s/6936cc13bc04

学习笔记——Redis基础

文章目录 Redis五种常用数据类型Redis常用命令Spring Data Redis使用方式操作步骤 Redis五种常用数据类型 Redis存储的是key-values结构的数据,其中key是字符串类型,value有五种常用的数据类型: 字符串(string)&…

C++入门基础知识32——【关于C++ 存储类之auto存储类】

成长路上不孤单😊【14后,C爱好者,持续分享所学,如有需要欢迎收藏转发😊😊😊😊😊😊😊!!!!&#xff…

Flex的基本使用+综合案例

组成 弹性盒子没有设置高&#xff0c;就会自动拉伸 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&q…

高并发下阻塞队列的选择

高并发下阻塞队列的选择 一、队列 队列&#xff1a;queue。简称队&#xff0c;它和堆栈一样&#xff0c;也是一种运算受限的线性表&#xff0c;其限制是仅允许在表的一端进行插入&#xff0c;而在表的另一端进行删除。 简单的说&#xff0c;采用该结构的集合&#xff0c;对元素…

洛谷 P2569 [SCOI2010] 股票交易

题目来源于&#xff1a;洛谷 题目本质&#xff1a;动态规划&#xff0c;单调队列 解题思路&#xff1a; 方程f[i][j]表示第 i 天结束后&#xff0c;手里剩下 j 股的最大利润&#xff0c;则不买不卖&#xff1a;f[i][j]f[i-1][j]。 买入&#xff1a;f[i][j]max{f[i-w-1][k]k*…

Spring DI 数据类型——构造注入

首先新建项目&#xff0c;可参考 初识 IDEA 、模拟三层--控制层、业务层和数据访问层 一、spring 环境搭建 &#xff08;一&#xff09;pom.xml 导相关坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.…

【Kubernetes】K8s 持久化存储方式

K8s 持久化存储方式 1.使用节点数据卷2.使用网络数据卷3.使用临时数据卷 由于容器是一种无状态的服务&#xff0c;所以容器中的文件在宿主机上表现出来的都是临时存放&#xff08;当容器崩溃或者重启时&#xff0c;容器中的文件会丢失&#xff09;。另外&#xff0c;Kubernetes…

C++领进门(第一讲)

目录 1. C关键字&#xff08;C98&#xff09; 2. 命名空间 ​编辑 2.1命名空间的定义 2.2命名空间的使用 3.C的输入&输出 3.1cout与printf的区别 4.缺省参数 4.1缺省函数的概念 4.2缺省参数分类 5.函数重载 C的语法就是在C的基础上弥补了C的缺陷与不足 1. C关键…

Java集合框架(三)---Map

接口Map<K,V> Map集合&#xff1a;该集合存储键值对&#xff0c;一对一对往里存&#xff0c;而且要保证键的唯一性。 1&#xff0c;添加 put(K key, V value) putAll(Map<? extends K, ? extends V> m) 2&#xff0c;删除 clear() remove(Object key) 3&#xff…

【鸿蒙学习】HarmonyOS应用开发者高级认证 - 应用DFX能力介绍(含闯关习题)

学完时间&#xff1a;2024年8月24日 学完排名&#xff1a;第1698名 一、Performance Analysis Kit简介 Performance Analysis Kit&#xff08;性能分析服务&#xff09;为开发者提供应用事件、日志、跟踪分析工具&#xff0c;可观测应用运行时状态&#xff0c;用于行为分析、…

游戏分享网站|基于SprinBoot+vue的游戏分享网站系统(源码+数据库+文档)

游戏分享网站 目录 基于SprinBootvue的游戏分享网站 一、前言 二、系统设计 三、系统功能设计 5.1系统功能模块 5.2后台登录 5.2.1管理员功能模块 5.2.2用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#x…

kaggle竞赛宝典 | 量化竞赛第一名的网络模型

本文来源公众号“kaggle竞赛宝典”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;量化竞赛第一名的网络模型 1 简介 今天我们重温Jane Street 大赛第一名的网络模型。该次赛事数据集包含了一组匿名的特征&#xff0c;feature_{0…

2014年4月-2023年上市公司秩鼎ESG评级数据

2014年4月-2023年上市公司秩鼎ESG评级数据 1、时间&#xff1a;2014年4月-2023年11月 2、来源:秩鼎数据 3、指标&#xff1a;证券代码、SC、评级日期、ESG评级、ESG等级、ESG得分、E评级、E等级、E得分、S评级、S等级、S得分、G评级、G等级、G得分、总市值(亿元)、流通市值(…

企业微信聊天记录可以保存多久?员工聊天记录查看指南!合规存档,助力企业规避风险!

在数字化办公的浪潮中&#xff0c;企业微信已成为企业沟通协作的重要工具。然而&#xff0c;聊天记录的保存时长与合规性管理&#xff0c;成为企业不可忽视的问题。 企业微信聊天记录云端最长可保存90天&#xff0c;但企业可根据需求自定义设置。本文将为您详细解析企业微信聊…

Linux TCP多线程服务器

一、多线程开发 线程和进程 程序写好存储在硬盘介质里&#xff0c;CPU读取程序到内存 &#xff0c;这个在内存中的可执行程序实例就叫进程。一个程序如果多次读取到内存中&#xff0c;那他们就是各自独立的进程 内存中的任何位置都有相应的地址方便访问&#xff0c;而在内存中…

8.23-docker基础命令学习

docker 1.docker容器 [rootdocker ~]# systemctl start docker[rootdocker ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos latest 5d0da3dc9764 2 years ago 231MB​# 容器执行完就退出了​[rootdocker ~]# docker run -it …

C++20中的简写函数模板(abbreviated function template)

简写函数模板(abbreviated function template):当占位符类型(auto或concept auto)出现在函数声明或函数模板声明的参数列表中时&#xff0c;该声明将声明一个函数模板&#xff0c;并且每个占位符的一个虚构模板参数(one invented template parameter)将附加到模板参数列表。如下…