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

单一责任原则

单一责任原则(Single Responsibility Principle, SRP)是面向对象设计中的一个重要原则,它是 SOLID 原则之一。SOLID 是五个面向对象设计原则的首字母缩写,这些原则有助于提高软件的可维护性和可扩展性。SRP 指的是每个类应该只有一个引起它变化的原因。

单一责任原则的核心思想

  • 单一原因变化:一个类应该只负责一项职责,并且仅由于该职责的变化而改变。
  • 职责分离:如果一个类承担了多个职责,那么应该考虑将其拆分为多个更小、更专注的类。
  • 降低耦合度:通过将职责分离,可以减少不同类之间的相互依赖,从而降低耦合度,使得系统更容易理解和维护。

示例说明

假设有一个类 Order,它负责处理订单以及发送电子邮件通知客户。根据单一责任原则,我们可以将这个类拆分为两个独立的类:

  1. Order: 负责处理订单的细节。
  2. NotificationService: 负责发送电子邮件通知。
原始代码示例
public class Order {private String customerEmail;public void placeOrder() {// 处理订单逻辑...sendEmailToCustomer();}private void sendEmailToCustomer() {// 发送电子邮件的逻辑...}
}
改进后的代码示例
public class Order {private NotificationService notificationService;private String customerEmail;public Order(NotificationService notificationService) {this.notificationService = notificationService;}public void placeOrder() {// 处理订单逻辑...// 通知服务发送电子邮件notificationService.sendEmail(customerEmail);}
}public class NotificationService {public void sendEmail(String email) {// 发送电子邮件的逻辑...}
}

在这个改进的例子中,Order 类只关注于处理订单,而发送电子邮件的任务交给了专门的 NotificationService 类。这样做有几个好处:

  • 更好的可测试性Order 类变得更加简单,更容易进行单元测试。
  • 更高的可维护性:如果发送电子邮件的逻辑发生变化,只需要修改 NotificationService 类,不会影响到 Order 类。
  • 更清晰的设计:每个类的职责更加明确,使得代码更易于理解。

应用到拼图游戏

我们可以考虑以下几个改进点以遵循单一责任原则:

  1. 分离界面和逻辑

    • 将游戏逻辑从 GameJFrame 中分离出来,创建一个新的类(如 GameLogic)来处理游戏的核心逻辑。
  2. 分离图像加载

    • 创建一个单独的类(如 ImageLoader)来负责图像的加载和显示。
  3. 分离键盘事件处理

    • 可以考虑将键盘事件处理逻辑封装到一个单独的类中,以便更好地管理输入。
  4. 分离菜单操作

    • 创建一个单独的类来处理菜单操作,如 MenuHandler

示例代码改进

以下是一个简化的示例,展示了如何将游戏逻辑分离到一个单独的类中:

public class GameLogic {private int[][] data;private int x;private int y;private int step;private int[][] win;private String path;public GameLogic() {data = new int[4][4];win = new int[][]{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};step = 0;path = "image\\man\\man1\\";}public void initData() {int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};Random r = new Random();for (int i = 0; i < tempArr.length; i++) {int index = r.nextInt(tempArr.length);int temp = tempArr[i];tempArr[i] = tempArr[index];tempArr[index] = temp;}for (int i = 0; i < tempArr.length; i++) {if (tempArr[i] == 0) {x = i / 4;y = i % 4;}data[i / 4][i % 4] = tempArr[i];}}public boolean victory() {for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if (data[i][j] != win[i][j]) {return false;}}}return true;}// ... 其他游戏逻辑方法 ...
}public class GameJFrame extends JFrame implements KeyListener, ActionListener {private GameLogic gameLogic;public GameJFrame(String usernameInput) {gameLogic = new GameLogic();initJFrame();initJMenuBar();gameLogic.initData();initImage();setVisible(true);}// ... 其他界面初始化方法 ...private void initImage() {this.getContentPane().removeAll();if (gameLogic.victory()) {JLabel winJLabel = new JLabel(new ImageIcon("image\\victory.png"));winJLabel.setBounds(203, 283, 197, 73);this.getContentPane().add(winJLabel);}JLabel stepCount = new JLabel("步数: " + gameLogic.step);stepCount.setBounds(30, 20, 100, 20);this.getContentPane().add(stepCount);for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {int num = gameLogic.data[i][j];JLabel jLabel = new JLabel(new ImageIcon(gameLogic.path + num + ".gif"));jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);jLabel.setBorder(new BevelBorder(1));this.getContentPane().add(jLabel);}}JLabel background = new JLabel(new ImageIcon("image\\background.png"));background.setBounds(40, 40, 508, 556);this.getContentPane().add(background);this.getContentPane().repaint();}// ... 其他方法 ...
}

通过这种方式,更好地组织代码,并使每个类专注于其核心职责,从而提高代码的质量和可维护性。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CentOS7上安装RabbitMQ
  • 正则表达式入门:Python ‘ re ‘ 模块详解
  • C++内存泄漏--**关于“异常0xc0000005 读取的位置 0xDDDDDDDD时发生冲突”
  • Flask详细教程
  • <STC32G12K128入门第十步>USB HID键盘
  • 5年前端面试之路
  • 【LeetCode Cookbook(C++ 描述)】一刷二叉树综合(下)
  • “AI+Security”系列第2期(三):面向LLM(大语言模型)的漏洞挖掘与对齐防御研究
  • 橙色简洁大气体育直播自适应模板赛事直播门户自适应网站源码
  • YOLOv10:实时端到端目标检测
  • Linux驱动学习之点灯(一)
  • SVN限制提交文件必须填写日志---实操笔记
  • 【杂乱笔记】Kmp字符串匹配算法
  • 鸿萌数据恢复服务:SQL Server 中的“PFS 可用空间信息不正确”错误
  • XSS游戏
  • JS 中的深拷贝与浅拷贝
  • 时间复杂度分析经典问题——最大子序列和
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • [case10]使用RSQL实现端到端的动态查询
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Angular数据绑定机制
  • es6
  • Idea+maven+scala构建包并在spark on yarn 运行
  • iOS 系统授权开发
  • JavaScript 一些 DOM 的知识点
  • Java程序员幽默爆笑锦集
  • JS变量作用域
  • maya建模与骨骼动画快速实现人工鱼
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • Spring框架之我见(三)——IOC、AOP
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 二维平面内的碰撞检测【一】
  • 前端自动化解决方案
  • 驱动程序原理
  • 使用docker-compose进行多节点部署
  • 用Python写一份独特的元宵节祝福
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • mysql面试题分组并合并列
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 仓管云——企业云erp功能有哪些?
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • # .NET Framework中使用命名管道进行进程间通信
  • # Panda3d 碰撞检测系统介绍
  • # Redis 入门到精通(九)-- 主从复制(1)
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • ######## golang各章节终篇索引 ########
  • $GOPATH/go.mod exists but should not goland
  • (09)Hive——CTE 公共表达式
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (不用互三)AI绘画工具应该如何选择
  • (简单) HDU 2612 Find a way,BFS。
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (排序详解之 堆排序)
  • (三)Honghu Cloud云架构一定时调度平台