设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列
系列文章目录
设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列
设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点
设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式,每一种模式的概念、使用场景和优缺点。
设计模式之模板方法模式,通俗易懂快速理解,以及模板方法模式的使用场景
设计模式之-建造者模式通俗易懂理解,以及建造者模式的使用场景和示列代码
设计模式之-代理模式,快速掌握理解代理模式,以及代理模式的使用场景
设计模式之-原型模式,快速掌握原型模式,通俗易懂的理解原型模式以及使用场景
设计模式之-中介者模式,快速掌握中介者模式,通俗易懂的讲解中介者模式以及它的使用场景
设计模式之-责任链模式,快速掌握责任链模式,通俗易懂的讲解责任链模式以及它的使用场景
设计模式之-装饰模式,快速掌握装饰模式,通俗易懂的讲解装饰模式以及它的使用场景
文章目录
- 系列文章目录
- 前言
- 一、什么是6大设计原则?以及它们的使用场景?
- 1.单一职责原则 (Single Responsibility Principle, SRP):
- 2. 里氏替换原则 (Liskov Substitution Principle, LSP):
- 3.依赖倒置原则 (Dependency Inversion Principle, DIP):
- 4.接口隔离原则 (Interface Segregation Principle, ISP):
- 5. 迪米特法则 (Law of Demeter, LoD):
- 6.开闭原则 (Open-Closed Principle, OCP):
- 二、代码示列
- 1.单一职责原则 (Single Responsibility Principle, SRP):
- 2.里氏替换原则 (Liskov Substitution Principle, LSP):
- 3.依赖倒置原则 (Dependency Inversion Principle, DIP):
- 4.接口隔离原则 (Interface Segregation Principle, ISP):
- 5.迪米特法则 (Law of Demeter, LoD):
- 6.开闭原则 (Open-Closed Principle, OCP):
- 使用场景
- 1.单一职责原则 (SRP):
- 2.里氏替换原则 (LSP):
- 3.依赖倒置原则 (DIP):
- 4.接口隔离原则 (ISP):
- 5.迪米特法则 (LoD):
- 6.开闭原则 (OCP):
前言
当谈论面向对象设计原则时,常常提到 SOLID 原则,这是一组面向对象设计的基本原则,旨在帮助开发人员设计出灵活、可维护和可扩展的软件系统。下面我将详细解释 SOLID 原则的原理,使用场景,以及代码示例。
一、什么是6大设计原则?以及它们的使用场景?
1.单一职责原则 (Single Responsibility Principle, SRP):
单一职责原则指的是一个类或模块应该有且只有一个职责。换句话说,一个类应该只负责一个逻辑单元或功能。这样做有助于提高代码的可读性、可维护性和可测试性,并降低类之间的耦合度。
2. 里氏替换原则 (Liskov Substitution Principle, LSP):
里氏替换原则要求子类能够替换掉父类,并且在不影响程序正确性的前提下,扩展或修改父类的行为。简而言之,子类应该能够以父类的身份无缝地替代使用,这样可以确保代码的稳定性和可靠性。
3.依赖倒置原则 (Dependency Inversion Principle, DIP):
依赖倒置原则强调高层模块不应该依赖于低层模块的具体实现,而是应该依赖于抽象接口。抽象接口应该定义高层模块所需的功能,而具体实现则由低层模块来提供。这样可以减少模块之间的直接依赖,提高代码的灵活性和可扩展性。
4.接口隔离原则 (Interface Segregation Principle, ISP):
接口隔离原则建议将大型接口拆分为更小、更具体的接口,以便客户端只依赖于它们所需的接口。这样可以避免客户端依赖于不需要的接口或方法,从而减少对不相关功能的依赖,提高代码的内聚性和可理解性。
5. 迪米特法则 (Law of Demeter, LoD):
迪米特法则也被称为最少知识原则,它强调一个对象应该尽量减少与其他对象之间的直接交互,只与它们的直接朋友进行通信。直接朋友包括该对象本身、被当作参数传递到方法中的对象、该对象的成员变量、方法内部创建的对象等。这样可以减少对象之间的耦合度,提高代码的可维护性和复用性。
6.开闭原则 (Open-Closed Principle, OCP):
开闭原则指的是软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,当需要添加新的功能时,应该通过扩展现有的代码来实现,而不是直接修改已有的代码。通过使用抽象化和多态等技术,可以实现代码的可扩展性和可维护性。
这些原则共同助力于构建可维护、灵活和可扩展的软件系统,它们在面向对象设计中具有重要意义,并且相互关联。遵循这些原则可以提高代码的质量和可读性,减少代码的耦合性,并为系统的演化和变化提供更好的支持。
二、代码示列
下面提供一些示例代码,以便更好地理解每个原则的实际应用。
1.单一职责原则 (Single Responsibility Principle, SRP):
class Customer {private String name;private String email;public void setName(String name) {this.name = name;}public void setEmail(String email) {this.email = email;}public void saveToDatabase() {// 保存客户数据到数据库}public void sendEmail() {// 发送电子邮件给客户}
}
在上述示例中,Customer类负责客户信息的管理和持久化到数据库,同时也负责发送电子邮件给客户。这违反了单一职责原则。更好的设计是将保存数据库和发送邮件的功能拆分到不同的类中。
2.里氏替换原则 (Liskov Substitution Principle, LSP):
class Rectangle {protected int width;protected int height;public void setWidth(int width) {this.width = width;}public void setHeight(int height) {this.height = height;}public int getArea() {return width * height;}
}class Square extends Rectangle {@Overridepublic void setWidth(int width) {super.setWidth(width);super.setHeight(width);}@Overridepublic void setHeight(int height) {super.setWidth(height);super.setHeight(height);}
}
在上述示例中,Square 类继承自 Rectangle 类,并重写了父类的设置宽度和高度的方法。然而,通过将一个 Square 对象赋值给 Rectangle 引用,可能会导致不符合预期的行为。这违反了里氏替换原则。更好的设计是将 Rectangle 和 Square 的关系改为使用组合而不是继承。
3.依赖倒置原则 (Dependency Inversion Principle, DIP):
interface MessageSender {void sendMessage(String message);
}class EmailSender implements MessageSender {public void sendMessage(String message) {// 发送电子邮件}
}class SMSender implements MessageSender {public void sendMessage(String message) {// 发送短信}
}class NotificationService {private MessageSender sender;public NotificationService(MessageSender sender) {this.sender = sender;}public void sendNotification(String message) {sender.sendMessage(message);}
}
在上述示例中,NotificationService 类依赖于抽象的 MessageSender 接口,而不是具体的实现类。这遵循了依赖倒置原则,高层模块(NotificationService)通过依赖于抽象接口(MessageSender)来与低层模块(EmailSender、SMSender)进行通信。
4.接口隔离原则 (Interface Segregation Principle, ISP):
interface Printer {void print();void scan();void fax();
}class SimplePrinter implements Printer {public void print() {// 打印}public void scan() {// 扫描}public void fax() {// 传真}
}class AdvancedPrinter implements Printer {public void print() {// 打印}public void scan() {// 扫描}public void fax() {// 传真}public void photocopy() {// 复印}
}
在上述示例中,Printer 接口定义了打印、扫描和传真的方法。然而,AdvancedPrinter 类实现了额外的 photocopy() 方法。这可能导致那些只需要基本打印功能的客户端依赖于不需要的方法,违反了接口隔离原则。更好的设计是将接口拆分为更小的接口,以便客户端只依赖于它们所需的接口。
5.迪米特法则 (Law of Demeter, LoD):
class Teacher {private String name;public Teacher(String name) {this.name = name;}public String getName() {return name;}
}class Course {private String name;private Teacher teacher;public Course(String name, Teacher teacher) {this.name = name;this.teacher = teacher;}public String getCourseInfo() {String teacherName = teacher.getName();return "Course: " + name + ", Teacher: " + teacherName;}
}class Student {private String name;public Student(String name) {this.name = name;}public void enrollCourse(Course course) {// 学生选课String courseInfo = course.getCourseInfo();// ...}
}
在上述示例中,Student 类通过调用 Course 的 getCourseInfo() 方法获取课程信息,而不是直接访问 Course 和 Teacher 的内部状态。这遵循了迪米特法则,减少了对象之间的耦合。
6.开闭原则 (Open-Closed Principle, OCP):
interface Shape {double calculateArea();
}class Rectangle implements Shape {private double width;private double height;public Rectangle(double width, double height) {this.width = width;this.height = height;}public double getWidth() {return width;}public double getHeight() {return height;}public double calculateArea() {return width * height;}
}class Circle implements Shape {private double radius;public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}public double calculateArea() {return Math.PI * radius * radius;}
}class AreaCalculator {public double calculateTotalArea(Shape[] shapes) {double totalArea = 0;for (Shape shape : shapes) {totalArea += shape.calculateArea();}return totalArea;}
}
在上述示例中,Shape 接口定义了 calculateArea() 方法,Rectangle 和 Circle 类实现了该接口并提供了各自的计算面积的方法。AreaCalculator 类可以通过接收一个 Shape 数组来计算所有形状的总面积,而无需修改现有的代码。这遵循了开闭原则,通过扩展 Shape 接口的实现类来添加新的形状,而无需修改已有的代码。
这些示例代码帮助说明了每个 SOLID 原则在具体的 Java 代码中的应用。请注意,这些原则并不是孤立的,它们相互关联,共同助力于构建可维护、灵活和可扩展的软件系统。
使用场景
1.单一职责原则 (SRP):
当一个类有多个责任时,应该将这些责任分离为不同的类。这样做可以提高类的内聚性,并使其更易于理解、维护和扩展。
使用场景:当一个类负责处理多个不同的功能或操作时,考虑将这些功能或操作分离到独立的类中,以确保每个类只负责一个单一的职责。
2.里氏替换原则 (LSP):
子类应该能够替代其父类,并且不会破坏程序的正确性。子类应该遵循父类的契约,并且可以在不引起意外行为的情况下进行替换。
使用场景:在继承关系中,确保子类可以无缝地替换父类,而不会导致不符合预期的行为。遵循 LSP 可以提高代码的可扩展性和灵活性。
3.依赖倒置原则 (DIP):
高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现细节,而具体实现应该依赖于抽象。
使用场景:通过使用接口或抽象类来定义模块之间的依赖关系,而不是依赖于具体的实现类。这样可以降低模块之间的耦合度,使系统更加灵活和可扩展。
4.接口隔离原则 (ISP):
客户端不应该依赖于它们不需要的接口。接口应该小而专注,应该根据客户端的需要进行划分。
使用场景:当一个接口变得庞大臃肿,或者一个类需要实现大量不相关的接口方法时,考虑将接口拆分为更小的、更具体的接口,以便客户端只依赖于它们所需的接口。
5.迪米特法则 (LoD):
一个对象应该尽可能少地了解其他对象,减少对象之间的直接依赖关系。模块之间的通信应该通过最少的接口进行。
使用场景:在类之间建立松散的耦合关系,避免对其他对象的直接依赖。通过只与必要的对象进行通信,可以降低代码的复杂性,并提高代码的可维护性。
6.开闭原则 (OCP):
软件实体应该对扩展开放,对修改关闭。即,应该通过扩展现有的代码来实现新的功能,而不是修改已有的代码。
使用场景:当需要添加新的功能或修改现有功能时,通过扩展而不是修改现有的代码来实现变化。这可以减少代码的脆弱性,并增加系统的可扩展性。
这些原则在软件设计和开发中广泛应用,它们有助于构建可维护、灵活和可扩展的代码。根据具体的场景和需求,可以根据需要选择适合的原则来指导设计和开发过程。
相关文章:
设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列
系列文章目录 设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列 设计模式之-单列设计模式,5种单例设计模式使用场景以及它们的优缺点 设计模式之-3种常见的工厂模式简单工厂模式、工厂方法模式和抽象工厂模式,每一种模式的概念、使用…...

css 实现满屏升空的气球动画
最终实现效果 demo放在最后了。。。。 问题一 怎么实现满屏气球?简单理解就是多个气球的合并,难道要写多个盒子吗?确实是这样子,但可以有更好的办法,其实就是通过原生操作多个盒子生成,所以只需要实现一个…...

批量归一化
目录 一、BN层介绍 1、深层神经网络存在的问题 2、批量归一化公式的数学推导 3、BN层的作用位置 4、 预测过程中的批量归一化 5、BN层加速模型训练的原因 6、总结 二、批量归一化从零实现 1、实现批量归一化操作 2、创建BN层 3、对LeNet加入批量归一化 4、开始训练…...

C语言:字符串字面量及其保存位置
相关阅读 C语言https://blog.csdn.net/weixin_45791458/category_12423166.html?spm1001.2014.3001.5482 虽然C语言中不存在字符串类型,但依然可以通过数组或指针的方式保存字符串,但字符串字面量却没有想象的这么简单,本文就将对此进行讨论…...

【开源】基于Vue+SpringBoot的新能源电池回收系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…...

共享和独享的区别是什么?有必要用独享IP吗?
通俗地讲,共享IP就像乘坐公共汽车一样,您可以到达目的地,但将与其他乘客共享旅程,座位很可能是没有的。独享IP就像坐出租车一样,您可以更快到达目的地,由于车上只有您一个人,座位是您一个人专用…...

leetcode——打家劫舍问题汇总
本章汇总一下leetcode中的打家劫舍问题,使用经典动态规划算法求解。 1、梦开始的地方——打家劫舍(★) 本题关键点就是不能在相邻房屋偷东西。 采用常规动态规划做法: 根据题意设定dp数组,dp[i]的含义为:…...

Java经典框架之Spring MVC
Spring MVC Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Spring MVC 入门案例 2. 基…...
Golang make vs new
文章目录 1.简介2.区别3.new 可以初始化 slice,map 和 channel 吗?4.make 可以初始化其他类型吗?5.小结参考文献 1.简介 在 Go 语言中,make 和 new 是两个用于创建对象的内建函数,但它们有着不同的用途和适用范围。 …...

Arthas
概述 Arthas(阿尔萨斯) 能为你做什么? Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: 这个类从哪个 jar 包加载的?为什么会…...

IP代理科普| 共享IP还是独享IP?两者的区别与优势
通俗地讲,共享IP就像乘坐公共汽车一样,您可以到达目的地,但将与其他乘客共享旅程,座位很可能是没有的。独享IP就像坐出租车一样,您可以更快到达目的地,由于车上只有您一个人,座位是您一个人专用…...

龙芯loongarch64服务器编译安装tensorflow-io-gcs-filesystem
前言 安装TensorFlow的时候,会出现有些包找不到的情况,直接使用pip命令也无法安装,比如tensorflow-io-gcs-filesystem,安装的时候就会报错: 这个包需要自行编译,官方介绍有限,这里我讲解下 编译 准备 拉取源码:https://github.com/tensorflow/io.git 文章中…...

开源持续测试平台Linux MeterSphere本地部署与远程访问
文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 前言 MeterSphere 是一站式开源持续测试平台, 涵盖测试跟踪、接口测试、UI 测试和性能测试等功能&am…...

Kubernetes(K8S)快速入门
概述 在本门课程中,我们将会学习K8S一些非常重要和核心概念,已经操作这些核心概念对应组件的相关命令和方式。比如Deploy部署,Pod容器,调度器,Service服务,Node集群节点,Helm包管理器等等。 在…...

将遗留系统分解为微服务:第 2 部分
在当今不断发展的技术环境中,从整体架构向微服务的转变对于许多企业来说都是一项战略举措。这在报销计算系统领域尤其重要。正如我在上一篇文章第 1 部分应用 Strangler 模式将遗留系统分解为微服务-CSDN博客中提到的,让我们探讨如何有效管理这种转变。 …...

RK3588平台开发系列讲解(AI 篇)RKNN-Toolkit2 模型的加载转换
文章目录 一、Caffe 模型加载接口二、TensorFlow 模型加载接口三、TensorFlowLite 模型加载接口四、ONNX 模型加载五、DarkNet 模型加载接口六、PyTorch 模型加载接口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 RKNN-Toolkit2 目前支持 Caffe、TensorFlow、Tensor…...

CNVD原创漏洞审核和处理流程
一、CNVD原创漏洞审核归档和发布主流程 (一)审核和归档流程 审核流程分为一级、二级、三级审核,其中一级审核主要对提交的漏洞信息完整性进行审核,漏洞符合可验证(通用型漏洞有验证代码信息或多个互联网实例、事件型…...

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据
注:本文所用技术栈为:springbootjdbcTemplatesqliteOkHttp 前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据,本文我们来获取个股的详细数据。 我们的数据源是某狐财经,接口的详细信息在下面的文章中,本…...

智能优化算法应用:基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于人工兔算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工兔算法4.实验参数设定5.算法结果6.参考文…...

【ubuntu 22.04】安装vscode并配置正常访问应用商店
注意:要去vscode官网下载deb安装包,在软件商店下载的版本不支持输入中文 在ubuntu下用火狐浏览器无法访问vscode官网,此时可以手动进行DNS解析,打开DNS在线查询工具,解析以下主机地址(复制最后一个IP地址&a…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...