设计模式之七大原则(一)——单一职责原则、开放-关闭原则
目录
- 一、设计模式的目的
- 二、设计模式的七大原则
- 1.单一职责原则
- 2.开放-关闭原则
一、设计模式的目的
设计模式的目的是为了提高代码重用性、可读性、可扩展性、可靠性,使得程序呈现出高内聚、低耦合的特性。
- 代码重用性(相同功能的代码,不用多次编写)
- 可读性(编程规范性,便于其他程序员的阅读和理解)
- 可扩展性(当需要增加新的功能时,非常的方便,称为可维护性)
- 可靠性(当我们增加新的功能时,对原来的功能没有影响)
- 使程序呈现高内聚、低耦合的特性
二、设计模式的七大原则
我们在设计一些设计模式时,一般遵循如下七项基本原则,它们分别是:
- 单一职责原则 (Single Responsibility Principle)
- 开放-关闭原则 (Open-Closed Principle)
- 里氏替换原则 (Liskov Substitution Principle)
- 依赖倒转原则 (Dependence Inversion Principle)
- 接口隔离原则 (Interface Segregation Principle)
- 迪米特法则(Law Of Demeter)
- 组合/聚合复用原则 (Composite/Aggregate Reuse Principle)
1.单一职责原则
单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。
- **降低类的复杂度。**一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
- **提高类的可读性。**复杂性降低,自然其可读性会提高。
- **提高系统的可维护性。**可读性提高,那自然更容易维护了。
- **变更引起的风险降低。**变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
简单说明一下,首先我们可以对某个类来说,即一个类应该只负责一项职责。如类A负责两个不同职责: 职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2。
以下假设一个场景并用代码演示(项目代码名称为SRP):
有一个鸟类,它会飞翔,用一个类描述鸟类飞行这个场景:
创建类Fly.java,代码如下:
public class Fly {public void birds(String birds){System.out.println(birds + "会在空中飞翔");}
}
创建运行类Client.java,代码如下:
public class Client{public static void main(String[] args){Fly fly = new Fly();fly.birds("老鹰");fly.birds("猫头鹰");fly.birds("喜鹊");}
}
运行结果如下所示:
老鹰会在空中飞翔
猫头鹰会在空中飞翔
喜鹊会在空中飞翔
在后来发现新问题,并不是所有的鸟类都会飞翔的,比如企鹅就不会了,修改时如果遵循单一职责原则的话,那么需要添加一个类
创建类NoFly.java,代码如下:
public class NoFly {public void birds(String birds){System.out.println("\n");System.out.println(birds + "不会在空中飞翔");}
}
修改运行类Client.java,代码如下:
public class Client{public static void main(String[] args){Fly fly = new Fly();fly.birds("老鹰");fly.birds("猫头鹰");fly.birds("喜鹊");NoFly noFly = new NoFly();noFly.birds("企鹅");}
}
运行结果如下所示:
老鹰会在空中飞翔
猫头鹰会在空中飞翔
喜鹊会在空中飞翔企鹅不会在空中飞翔
2.开放-关闭原则
开放封闭原则就是软件实体应该对扩展开放,而对修改封闭。开放封闭原则是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化,降低耦合,而开放封闭原则正是对这一目标的最直接体现。
开放封闭原则主要体现在两个方面:
- 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
- 对修改封闭,意味着类一旦设计完成,就可以独立其工作,而不要对类尽任何修改。
如果一个软件能够满足 OCP 原则,那么它将有以下两项优点:
- 能够扩展已存在的系统,能够提供新的功能满足新的需求,因此该软件有着很强的适应性和灵活性。
- 已存在的模块,特别是那些重要的抽象模块,不需要被修改,那么该软件就有很强的稳定性和持久性
开闭原则的实现方法
- 通过“抽象约束、封装变化”来实现开闭原则
- 参数类型,引用对象尽量使用接口或抽象类,而不是现实类;
- 通过接口或抽象类为软件实体定义一个相对稳定的抽象层,一旦确定就不允许修改;
- 将相同的变化封装到一个接口或抽象类中;
- 将不同的变化封装到不同的接口或抽象类中;
以下假设一个场景并用代码演示(项目代码名称为OCP):
以商场卖东西为例:
创建类shopping.java,代码如下:
public class Shopping {public static void main(String[] args) {Shop shopping = new Shop();shopping.shop(new Apple());shopping.shop(new Pear());shopping.shop(new Watermelon());}
}class Shop {public void shop(Type s) {if (s.type == 1) {apple(s);} else if (s.type == 2) {pear(s);} else if (s.type == 3) {watermelon(s);}}//出售苹果public void apple(Type r) {System.out.println(" 出售苹果 ");}//出售梨public void pear(Type r) {System.out.println(" 出售梨 ");}//出售西瓜public void watermelon(Type r) {System.out.println(" 出售西瓜 ");}
}class Type {int type;
}class Apple extends Type {Apple() {super.type = 1;}
}class Pear extends Type {Pear() {super.type = 2;}
}class Watermelon extends Type {Watermelon() {super.type = 3;}}
运行结果如下所示:
出售苹果 出售梨 出售西瓜
修改代码,改为用OCP原则:
创建代码ShoppingOCP.java,代码如下:
public class ShoppingOCP {public static void main(String[] args) {ShopOCP shopping = new ShopOCP();shopping.shop(new Apple1());shopping.shop(new Pear1());shopping.shop(new Watermelon1());shopping.shop(new Cherry1());}
}class ShopOCP {public void shop(Type1 s) {s.type1();}
}abstract class Type1 {abstract void type1();
}class Apple1 extends Type1 {@Overridevoid type1() {System.out.println(" 出售苹果 ");}
}class Pear1 extends Type1 {@Overridevoid type1() {System.out.println(" 出售梨 ");}
}class Watermelon1 extends Type1 {@Overridevoid type1() {System.out.println(" 出售西瓜 ");}
}class Cherry1 extends Type1 {@Overridevoid type1() {System.out.println(" 出售樱桃 ");}
}
运行结果如下所示:
出售苹果 出售梨 出售西瓜 出售樱桃
把创建Type1 类做成抽象类,并提供一个抽象的 type方法,让子类去实现即可,这样我们有新的水果种类时,只需要让新的水果类继承 Type1 ,并实现 type方法即可,使用方的代码就不需要修改了, 从而满足了开闭原则。
以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git
相关文章:
设计模式之七大原则(一)——单一职责原则、开放-关闭原则
目录一、设计模式的目的二、设计模式的七大原则1.单一职责原则2.开放-关闭原则一、设计模式的目的 设计模式的目的是为了提高代码重用性、可读性、可扩展性、可靠性,使得程序呈现出高内聚、低耦合的特性。 代码重用性(相同功能的代码,不用多…...
C++ set、unordered_set、multiset它们之间的区别与一些使用方法(不断更新)
set、unordered_set、multiset是什么?以及它们之间的区别 首先,它们三个都是C标准库提供的关联容器中的一种。只不过set、multiset容器是有序的,而unordered_set容器是无序的 std::set 是 C 标准库中的一个容器,其存储的元素按设…...

hadoop调优
hadoop调优 1 HDFS核心参数 1.1 NameNode内存生产配置 1.1.1 NameNode内存计算 每个文件块大概占用150byte,如果一台服务器128G,能存储的文件块如下 128 (G)* 1024(MB) * 1024(KB) * 1024(Byte) / 150 Byte 9.1 亿 1.1.2 Hadoop2.x 在Hadoop2.x中…...

EM@三角函数诱导公式
文章目录诱导公式单位圆坐标和三角函数记忆口诀符号看象限奇变偶不变例常用诱导公式🎈常用部分(5对)倒数关系六种三角函数间的转换关系小结ReflectionsShifts and periodicity诱导公式 诱导公式 - 维基百科,自由的百科全书 (wikipedia.org) 单位圆坐标…...

是不是只能学IT互联网技术才有发展前途?
当然不是,三百六十行,行行出状元。 但我们需要认清一个现实是,我们正处于一个信息爆炸的时代,掌握紧跟潮流的技术,才可以让我们更自信地面对每天的生活,才有多余的精力、财力来享受生活。“人生在世&#…...
Linux 进程:exit和_exit的辨析
目录1.接口与函数2.缓冲区3.exit 与 _exit(1)_exit(2)exit这里来认识exit函数和 _exit接口 ,它们的作用是类似的,都是在调用后退出程序,可以在程序的任何地方调用。 1.接口与函数 exit函数和_exit接口,一个函数,一个…...

智能电子标签——商超版价签
2.1英寸TFT黑白电子价签 ★ 快速变价,高效运营 ★ 市场实用,布局物联网未来 ★ 更好客户体验 ★ 降低系统成本,具备竞争力 ★ 2.1英寸黑白红电子价签 ★ 电池低能耗,常规使用三年 ★ 穿透力强不慣障碍 ★ 2.4G载波&#x…...

计算机网络自检
1 计网体系结构 因特网结构: 计网三个组成成分: 工作方式-其中2个部分: 功能-两个子网: 5个XAN分别是: 传输技术,两者的主要区别: 4种基本网络拓扑结构: 3种交换技术: 协…...

DC真实数据都有哪些?Filecoin为DC数据存储的解决方案又是什么?
对于生活在数字时代的我们而言,数据或许就和平日呼吸的空气一样,已经不需要我们再去思考其概念。我们的日常生活中无时无刻都有数据的身影,日常的购物消费、出行、学习、记录,当我们每天生活有数字化加持的小区里,工作…...

解决vscode无法自动更新
一.前言 要在vscode里面安装插件,被提示版本不匹配,然后得更新,然后我发现我的'帮助'菜单栏下没有检查更新,然后我去&…...

315线上知识竞赛答题活动方案及模板分享
315线上知识竞赛答题活动方案及模板分享在315国际消费者权益日来临之际, 很多单位推出有奖知识竞答, 希望大家在了解专业知识的同时, 还可以拿到自己喜欢的奖品!这是消费者委员会和监管局联合举办的“315消费知识在线有奖竞答”活…...

论文复现-2:代码部分
以CONLL03数据集为例 文章目录1 整体框架2 数据结构2.1 原始数据集2.2 处理之后的数据集3 代码部分3.0 模型参数3.1 数据预处理3.2 模型方法3.1.1 定义表示的学习权重项的学习双塔模型3.2.2 forward3.3 损失函数3.4 训练与推理Ablation study训练实例1 整体框架 任务是实体识别…...

Linux开放的端口太多了?教你一招找出所有开放的端口,然后直接干掉!
基于服务器安全性维护的目的,查看所有开放的端口是通常采取的第一步,从中检查出可疑或者不必要的端口并将其关掉。关于查看开放的端口,方法不止一种,比如lsof 命令,还可以使用 ss 命令。 查看开放的端口 今天我们就介…...

mysql集群简介
集群的好处 高可用性:故障检测及迁移,多节点备份。 可伸缩性:新增数据库节点便利,方便扩容。 负载均衡:切换某服务访问某节点,分摊单个节点的数据库压力。 集群要考虑的风险 网络分裂:群集还…...

装饰器模式
概述 当我们编写软件时,有时我们会遇到需要在不修改现有代码的情况下添加新功能的情况。这时,我们可以使用装饰器模式。 装饰器模式是一种结构性设计模式,它允许我们在不改变对象接口的情况下动态地向对象添加功能。装饰器模式通过创建一个…...

21 Nacos客户端本地缓存及故障转移
Nacos客户端本地缓存及故障转移 在Nacos本地缓存的时候有的时候必然会出现一些故障,这些故障就需要进行处理,涉及到的核心类为ServiceInfoHolder和FailoverReactor。 本地缓存有两方面,第一方面是从注册中心获得实例信息会缓存在内存当中&a…...
遍历读取文件夹下的所有文件
遍历读取文件夹下的所有文件 例如,读取文件夹下,子文件夹的所有的jpg文件: import glob path "./database/20230302/night/*/*.jpg"#设置自己的文件夹路径以及文件 image_files glob.glob(path, recursiveTrue)for image_file …...

nexus安装与入门
安装 nexus-3.31.1-01-unix.tar.gz 链接:https://pan.baidu.com/s/1YrJMwpGxmu8N2d7XMl6fSg 提取码:kfeh 上传到服务器,解压 tar -zvxf nexus-3.31.1-01-unix.tar.gz进入bin目录,启动 ./nexus start查看状态 ./nexus status默…...

Flink SQL Checkpoint 学习总结
前言 学习总结Flink SQL Checkpoint的使用,主要目的是为了验证Flink SQL流式任务挂掉后,重启时还可以继续从上次的运行状态恢复。 验证方式 Flink SQL流式增量读取Hudi表然后sink MySQL表,任务启动后处于running状态,先查看sin…...

2023年“楚怡杯“湖南省职业院校技能竞赛“网络安全”竞赛任务书
2023年“楚怡杯“湖南省职业院校技能竞赛“网络安全”竞赛任务书 一、竞赛时间 总计:360分钟 竞赛阶段竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略配置 A-3 流量完整性保护 A-4 事件监控 …...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...