【设计模式】六大原则-下

❓首先什么是设计模式?

😵相信刚上大学的你和我一样,在学习这门课的时候根本不了解这些设计原则和模式有什么用处,反而不如隔壁的C++更有意思,至少还能弹出一个小黑框,给我个hello world。

✨ 如何你和我一样也是这么想,那接下来咱们以贴合生活实际的方式来看看设计模式到底有什么神奇的地方

😄更多有趣的设计模式讲解都在设计模式👍专栏,欢迎来看看🎉🎉🎉。

【设计模式】六大原则-下

  • 六大原则-下
    • 单一职责
    • 接口隔离原则
    • 合成复用原则
  • 总结

新来的小伙伴你可能会注意到,这咋直接六大原则下了,上呢?

别着急,这里有一个传送门,大家可以看看上半部分的内容。
🆒传送门🆒 【设计模式】六大原则-上

接下来咱们一起看看另外三个原则

六大原则-下

单一职责

每个类应该只有一个引起它变化的原因,即一个类只负责一项职责。

哦吼,熟悉的感觉,还是这么抽象!

在这里插入图片描述

害,咱们一起看看这是啥意思

相信大家读完之后就知道这条原则说的是啥,就是一个类只负责一项功能,但有一个问题,为啥一个类只负责一个功能呢?

举个例子哈,现在我们做了一个图书管理系统,然后有一个类,负责订单的处理,如下所示

public class OrderManager {// 创建订单public void createOrder(Order order) {// 创建订单的逻辑System.out.println("Order created: " + order.getId());}// 取消订单public void cancelOrder(Order order) {// 取消订单的逻辑System.out.println("Order canceled: " + order.getId());}// 计算订单总价public double calculateTotal(Order order) {double total = 0.0;for (OrderItem item : order.getItems()) {total += item.getPrice() * item.getQuantity();}// 假设税费是总价的10%total += total * 0.1;return total;}// 生成订单报表public void generateOrderReport(Order order) {// 生成订单报表的逻辑System.out.println("Order Report for Order ID: " + order.getId());System.out.println("Total Price: " + calculateTotal(order));}// 持久化订单public void saveOrder(Order order) {// 保存订单的逻辑System.out.println("Order saved to database: " + order.getId());}
}

这样有啥问题吗

  • 首先,这个代码太复杂了,我们现在还没有加上具体的处理流程,整个代码已经非常长了,理解起来非常困难。
  • 其次,修改存在风险。我们可以看到generateOrderReport调用了calculateTotal方法,如果以后我们因为其他的需求进行了改动,例如打折促销修改了计算总价的方式,generateOrderReport极有可能出现问题。

那怎么做呢?

就可以按照单一职责原则进行修改,修改起来非常简单,就是直接为每一个方法创建一个类即可,如下

public class OrderCalculator {public double calculateTotal(Order order) {double total = 0.0;for (OrderItem item : order.getItems()) {total += item.getPrice() * item.getQuantity();}// 假设税费是总价的10%total += total * 0.1;return total;}
}
public class OrderReportGenerator {private final OrderCalculator calculator;public OrderReportGenerator(OrderCalculator calculator) {this.calculator = calculator;}public void generateOrderReport(Order order) {// 生成订单报表的逻辑System.out.println("Order Report for Order ID: " + order.getId());System.out.println("Total Price: " + calculator.calculateTotal(order));}
}

现在,我们可以很轻松的搞清楚这个类是干什么的,可读性增强了。

并且,上面我们提到的如果打折怎么办?

我们完全可以为OrderCalculator添加一个接口,这样如果有新的结算策略的时候,增加一个实现类就好了。

**看到这,是不是有点熟悉,这是不是就是所谓的对修改封闭,对扩展开放,开闭原则。**代码如下

public interface CalculatorInterface {public double calculateTotal(Order order);
}public class OrderCalculator implements  CalculatorInterface {public double calculateTotal(Order order) {double total = 0.0;for (OrderItem item : order.getItems()) {total += item.getPrice() * item.getQuantity();}// 假设税费是总价的10%total += total * 0.1;return total;}
}public class DiscountCalculator implements  CalculatorInterface {public double calculateTotal(Order order) {double total = 0.0;//  打折操作return total;}
}

接口隔离原则

不应该强迫客户依赖它们不使用的方法。应该将臃肿的接口分解为更小、更具体的接口,这样客户只需知道它们感兴趣的方法即可。

这个是啥意思呢?

大白话翻译一下就是,我们设计的接口的功能应该尽可能细粒,不要让一个接口实现的功能太大,尽量细化一点。

例如,我们现在写一个包饺子的接口,如下所示

public interface MakeDumpling {void cook();
}public class MakeDumplingImpl implements MakeDumpling {@Overridepublic void cook() {System.out.println("调馅");System.out.println("擀面皮");System.out.println("包饺子");System.out.println("下锅");}
}

整体实现的还是很简单的哈,但现在有一个问题,我想要包包子,你就会发现,我们需要新定义一个接口,并且需要把调馅,擀面皮和下锅这些重复的操作代码再写一遍。

看到这,不知道你有没有意识到为什么要遵守接口隔离原则。

那我们怎么改呢

public interface interface1 {
//  擀面皮void rollTheDough();
}public interface interface1 {//  调饺子馅void mixDumplingFilling();
}

这样是不是就把功能更细化了一点,我们就可以提高代码的复用性了。

合成复用原则

尽量使用对象组合而不是继承来实现代码复用。组合可以在运行时选择或改变行为,使得系统更具灵活性。

这个比较简单一点,其实读过就明白了。很符合我们的认知哈。先看看比较官方的解释

合成复用原则是一种重要的设计原则,旨在通过组合或聚合关系来实现代码的复用,而非过度依赖继承关系。该原则强调优先使用对象组合来达到复用的目的,从而降低类与类之间的耦合度,提高系统的灵活性和可维护性

太官方了有点看不懂,咱来点通俗解释。

为啥能降低耦合呢?

咱们想一下这样一个场景,你设计的系统中大部分类都继承了一个父类。但是现在由于业务变化,父类对一个方法的参数进行了修改,那好嘛,所有子类都要改,这是不是有点难受

那为啥能提高灵活性呢

想一下这样的场景,B类继承了A类,并使用了A的operate方法,但是现在出现了一个问题,C类也提供一个operate方法,并且我需要动态选择使用A或则C的方法,那继承很明显不行,那没办法,整不了。但如果使用组合的方式呢,我们可以动态的选择A或C的方法,灵活性就大大提升了。

总结

六大原则就全部介绍完了。

在这里插入图片描述

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

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

相关文章

ArcGIS Pro基础:状态栏显示栏的比例尺设置和经纬度位置

上图所示,界面下方最左侧是显示的比例尺,可以进行选择设置,也可以进行自定义设置 上图所示,可以手动录入比例尺,同时也可以对比例尺设置别名,比如【实验1】作为特定比例尺的标记 如上图所示,可以…

KEEPALIVED高可用集群最详解

目录 一、高可用集群 1.1 集群的类型 1.2 实现高可用 1.3 VRRP:Virtual Router Redundancy Protocol 1.3.1 VRRP相关术语 1.5.2 VRRP 相关技术 二、部署KEEPALIVED 2.1 keepalived 简介 2.2 Keepalived 架构 2.3 Keepalived 环境准备 2.3.1 实验环境 2…

嵌入式初学-C语言-二七

文件操作 概述: 什么是文件: 是保存在外存储器(磁盘,u盘,移动硬盘等等)上的数据的集合。 文件操作体现在哪几个方面: 文件内容的读取文件内容的写入 数据的读取和写入可被视为针对文件进行…

Day42 | 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II

语言 Java 739. 每日温度 每日温度 题目 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该…

关于windows环境使用nginx的一些性能问题

遇到的问题 最近在一个windows环境中部署nginx,遇到了以下问题: 1. nginx启动了九个线程(1master8woekr),但是所有链接都被1个woker接收,其余worker不工作 2. 用户端访问web很慢,登录服务器使…

k8s搭建

环境: 操作系统:win10 虚拟机:virtual box linux发行版:CentOS7.9 linux内核(使用uname -r查看):3.10.0-957.el7.x86_64 master和node节点通信的ip(master): 10.0.0.198 0.检查配置 本次搭建的集群共三个节…

deepspeed的并行模式介绍笔记

1.整体框架 2.并行模式 1.数据并行DDP 数据切分以后,分开单张卡训练得到参数,然后综合在单卡计算。 要点:前向计算和反向计算两步骤走并汇总。 1.前向计算 需要留一块主卡一定空间用于综合。 2.反向传播 利用前向传播的汇总参数得到各个…

Leetcode Java学习记录——动态规划基础

概念 首先想到递归、分治。动态规划本质也一样。 共性:找到重复子问题 差异性:有最优子结构,中途可以淘汰次优解。 动态规划是分治最优子结构。 例题 斐波那契数列 递归实现,时间复杂度是指数级。 最基础的写法为 int fib(i…

Linux CentOS java JDK17

1. 下载 cd /usr/local/ wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz 2. 解压 tar -zxf jdk-17_linux-x64_bin.tar.gz 3.配置环境变量 vim /etc/profile // 在末尾处添加 export JAVA_HOME/usr/local/jdk-17.0.12 #你安装jdk的路径&…

idea和jdk的安装教程

1.JDK的安装 下载 进入官网,找到你需要的JDK版本 Java Downloads | Oracle 中国 我这里是windows的jdk17,选择以下 安装 点击下一步,安装完成 配置环境变量 打开查看高级系统设置 在系统变量中添加两个配置 一个变量名是 JAVA_HOME …

大模型日报|10 篇必读的大模型论文

大家好,今日必读的大模型论文来啦! 1.斯坦福推出大模型网络安全能力和风险评估框架 Cybench 用于网络安全的语言模型智能体(agent)能够自主识别漏洞并执行漏洞利用,有可能对现实世界造成影响。政策制定者、模型提供者…

vue通过iframe预览 pdf、word、xls、ppt、txt文件

vue通过iframe预览 pdf、word、xls、ppt、txt文件 iframe中预览只能直接打开pdf文件&#xff0c;其他文件需要通过office365预览。 效果&#xff1a; 组件代码&#xff1a; <!--* fileName: 文件预览-FileView.vue* date: yanghaoxing-2024-08-16 09:32:24 !--> <…

ModuleNotFoundError: No module named ‘pywin32_bootstrap

ModuleNotFoundError: No module named ‘pywin32_bootstrap 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社…

4.展示功能的测试及缓冲-《篮球比赛展示管理系统》现场管理员角色操作手册

本平台属于富客户端类型&#xff0c;展示元素包括精美图片、高级动画、透明视频等&#xff0c;所以为了保证画面的呈现速度&#xff0c;一定要在比赛之前&#xff0c;把所有的展示功能在电脑过一遍&#xff0c;浏览器自动产生一个数据缓冲&#xff0c;便于提高现场画面的展示放…

springboot的学习(三):开发相关

简介 一些开发测试时用到的技术。 springboot 热部署 修改了代码&#xff0c;服务器不需要重启可以直接看到新的修改的效果。仅仅加载当前开发者自定义开发的资源&#xff0c;不加载jar资源。 在pom.xml配置文件中添加&#xff1a; <dependency><groupId>org.s…

飞书操作—学习笔记

1&#xff1a;推荐飞书的理由 这几年越来越多的公司开始使用飞书这一款软件&#xff0c;即是是一些大厂&#xff0c;也开始边缘化内部的通讯交流软件。那么飞书有那些功能能得到这样的青睐喃&#xff1f; 我个人总结&#xff0c;飞书有如下优势 1&#xff1a;飞书功能相对来…

24年银行从业资格考试报名照规格要求

24年银行从业资格考试报名照规格要求 #银行从业 #银行从业资格证 #银行从业考试 #银行从业资格考试 #银行从业资格证报名照片 #银从

Linux | 深入探究Linux进程控制:从fork函数到进程等待再到进程替换

目录 1、进程的创建&#xff1a;fork函数 2、父子进程的奇怪现象&#xff1a;为什么同一个地址有不同的值&#xff1f;——区分内存的虚拟地址和物理地址 代码&#xff1a;利用fork函数的返回值进行父子进程分流&#xff0c;执行不同的代码块 虚拟地址和物理地址&#xff1…

推荐编译器插件:Fitten Code 更快更好的AI助手

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【Linux 驱动】IMX6ULL gpio驱动

1. 概述 如果 pinctrl子系统将一个 PIN 复用为 GPIO 的话&#xff0c;那么接下来要用到 gpio 子系统了。gpio 子系统顾名思义&#xff0c;就是用于初始化 GPIO 并且提供相应的 API 函数&#xff0c;比如设置 GPIO为输入输出&#xff0c;设置读取 GPIO 的值等。 gpio 子系统的主…