设计模式之-6大设计原则简单易懂的理解以及它们的适用场景和代码示列

文章目录

  • 前言
  • 一、什么是6大设计原则?以及它们的使用场景?
    • 1.单一职责原则 (Single Responsibility Principle, SRP):
    • 3.依赖倒置原则 (Dependency Inversion Principle, DIP):
    • 4.接口隔离原则 (Interface Segregation Principle, ISP):
    • 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):

软件实体应该对扩展开放,对修改关闭。即,应该通过扩展现有的代码来实现新的功能,而不是修改已有的代码。
使用场景:当需要添加新的功能或修改现有功能时,通过扩展而不是修改现有的代码来实现变化。这可以减少代码的脆弱性,并增加系统的可扩展性。

这些原则在软件设计和开发中广泛应用,它们有助于构建可维护、灵活和可扩展的代码。根据具体的场景和需求,可以根据需要选择适合的原则来指导设计和开发过程。

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

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

相关文章

文化旅游数据合集,多个数据分享~有图有数据

本周我们将分享一类数据分析常用的数据类型——文化旅游,这里将我们目前所上线的文化旅游类相关数据进行汇总,后续也会持续更新~ 1、全国博物馆数据 基本信息. 数据名称: 全国博物馆数据 数据格式: shpexcel 数据几何类型: 点 数据坐标系: WGS84 …

【MYSQL】MYSQL 的学习教程(五)之 MySQL 索引底层:B+ 树详解

1. 树 树跟数组、链表、堆栈一样,是一种数据结构。它由有限个节点,组成具有层次关系的集合。因为它看起来像一棵树,所以得其名。一颗普通的树如下: 关于树的概念: 结点的度:一个结点含有的子结点个数称为该结点的度树…

C/C++ 块作用域的静态变量static的应用

块作用域的静态变量 静态变量(static variable)听起来自相矛盾,像是一个不可变的变量。实际上,静态的意思是该变量在内存中原地不动,并不是说它的值不变。具有文件作用域的变量自动具有(也必须是)静态存储器。创建的具…

小红书kos和kop有什么区别,营销玩法有哪些

相信熟悉媒介传播的朋友,对于kol和koc都不陌生。但随着平台的发展和市场的进步,又出现了kos和kop。那么小红书kos和kop有什么区别,营销玩法有哪些? 一、什么是kos和kop KOS,全称叫做Key Opinion Sales,意思…

数据恢复工具推荐!这3款堪称删除文件恢复大师!

“快看看我!经常都会莫名奇妙丢失各种电脑文件,但是又无法通过简单的方法找回重要的数据,有没有什么简单的操作可以帮助我快速恢复数据的呀?非常感谢!” 在我们的日常生活中,无论是工作还是学习&#xff0c…

搭载紫光展锐芯的移远通信RedCap模组顺利通过中国联通OPENLAB实验室认证

近日,移远通信联合紫光展锐在中国联通5G物联网OPENLAB开放实验室,完成了RedCap模组RG207U-CN端到端测试验收,并获颁认证证书。移远通信RG207U-CN成为业内率先通过联通OPENLAB认证的紫光展锐RedCap芯片平台的模组。 本次测试基于联通OPENLAB实…

千呼万唤始出来!《繁花》定档央八

各位久等! 冰雪消融,繁花倾情绽放 央八好戏,即将开场 12月27日19:30起 电视剧《繁花》 登陆CCTV-8黄金强档 接下来 随宝总一起回到九十年代的上海 上世纪九十年代初 煌煌大时代,人人争上游 青年阿宝拜商界高手爷叔为师 左…

java中将Map集合、对象、字符串转换为JSON对象

1、Map集合转JSON对象 创建一个Map集合&#xff1b; 新建json对象&#xff0c;并将Map引入json中。 public void demo1(){ //创建一个Map集合Map<String, String> map new HashMap<>();map.put("1729210001","zhangsan");map.put("17292…

paddle 53 基于PaddleClas2.5训练自己的数据(训练|验证|推理|c++ 部署)

项目地址:https://github.com/PaddlePaddle/PaddleClas 文档地址:https://paddleclas.readthedocs.io/zh-cn/latest/tutorials/install.html paddleclas的最新项目已经不适应其官网的使用案例(训练、验证、推理命令均不适用),为此博主对其进行命令重新进行修改。同时padd…

山海鲸开发者解读智慧电力

作为山海鲸可视化软件的开发者&#xff0c;我们深知可视化技术在智慧电力领域的重要性。在这个能源紧缺、环保意识日益增强的时代&#xff0c;在开发免费好用的可视化软件同时&#xff0c;我们也希望通过数字孪生技术为智慧电力领域提供高效、智能的解决方案&#xff0c;推动电…

若依框架跑起来,Java小白入门(一)

背景 本人Java小白&#xff0c;有一点编程基础&#xff08;c#&#xff09;。企业数字化建设大环境是JAVA&#xff0c;所以需要搞起来&#xff0c;而学习最快的方式就是读代码&#xff0c;学以致用干项目。所以这个系列就是从小白看能否变成小黑。码云上有很多框架&#xff0c;…

剑指Offer 队列栈题目集合

目录 用两个栈实现队列 用两个栈实现队列 刷题链接&#xff1a; https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6 题目描述 思路一&#xff1a; 使用两个栈来实现队列的功能。栈 1 用于存储入队的元素&#xff0c;而栈 2 用于存储出队的元素。 1.push…

Java|IDEA 中添加编译参数 --add-exports

方法1 File > Settings > Build, Execution, Deployment > Compiler > Java Compiler > Javac Options > Override compiler parameters per-module 点击&#xff1a; 点击OK 双击Compliation options&#xff0c;输入后回车&#xff1a; 方法2 找到出错…

KubeSphere应用【五】发布镜像至Harbor

一、IDEA发布镜像至Docker 1.1IDEA安装Docker插件 1.2配置Docker服务器地址 1.3编写POM.XML文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/20…

Tg2520smn ((tcxo / vc-tcxo)高稳定性)

TG2520SMN是一款高稳定性的(TCXO/VC-TCXO)产品&#xff0c;其频率输出范围为10MHz至55MHz&#xff0c;提供多种电源电压选项&#xff0c;分别为1.8 V类型、2.8 V类型、3.0 V类型和3.3 V类型&#xff0c;该产品具备优异的频率/温度特性&#xff0c;最大的频率稳定性为0.5 10^6 …

SpringIOC之BeanFactoryResolver

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

智能感知时代已来,汉威科技柔性传感器迎来发展新机遇

近年来&#xff0c;消费电子、医疗健康、智能汽车、人机交互等领域的黑科技产品不断出现&#xff0c;催生了许多新功能、新场景、新市场。 TWS耳机&#xff1a;许多TWS&#xff08;真无线立体声&#xff09;耳机厂商开始摒弃传统的触摸感应模式&#xff0c;转而采用最先进的压…

【算法刷题】Day22

文章目录 1. 按摩师题干&#xff1a;算法原理&#xff1a;&#xff08;dp&#xff09;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. 寻找数组的中心下标题干&#xff1a;算法原理&#xff1a;&#xff08;前缀和&#xff09;代码…

vue 简单实现购物车:商品基础信息最终的 html 文件 + 商品计数器的组件处理,实现了购物车;

购物车实现过程&#xff1a; Ⅰ、商品购物车作业需求&#xff1a;1、商品购物车页面示例&#xff1a;2、具体需求&#xff1a; Ⅱ、html 文件的构建&#xff1a;商品购物车.html Ⅲ、组件文件的构建&#xff1a;商品购物车1.js Ⅳ、小结&#xff1a; Ⅰ、商品购物车作业需求&am…

android 使用GSON 序列化对象出现字段被优化问题解决方案

一、问题描述 有以下结构&#xff1a; public class NativeParam<T> {private T data;public NativeParam(T data) {this.data data;}public T getData() {return data;}public void setData(T data) {this.data data;} };NativeParam<String> data "1.0…