面向对象设计的七大设计原则

news2024/12/22 20:40:28

# 面向对象设计的七大设计原则

在我们探讨如何创建健壮且可维护的面向对象系统时,有一些原则可以为我们提供指导。这些原则可以帮助我们理解如何最好地组织我们的类和对象,以实现高效、模块化和可扩展的设计。在本篇文章中,我们将探讨这些原则,以及如何在我们的设计中应用它们。

单一职责原则 (Single Responsibility Principle, SRP)

单一职责原则是指一个类应该只有一个引起变化的原因。这可能听起来有些抽象,但实际上,这是一个非常强大的概念。当我们设计一个类时,我们通常被诱惑去让它做更多的事情。然而,当一个类的职责过多时,它就会变得复杂且难以维护。

例如,我们可能有一个User类,它负责管理用户的信息,如用户名、密码等。然而,如果我们还让这个类负责验证用户、管理用户的登录状态、处理用户的购物车等,那么这个类就会变得非常复杂。

通过确保每个类只有一个职责,我们可以降低类的复杂性,使其更易于理解和维护。此外,当需求发生变化时,我们只需要修改负责该职责的类,而不会影响到其他的代码。

开放封闭原则 (Open-Closed Principle, OCP)

开放封闭原则是指软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这个原则的主要思想是,我们应该能够在不修改现有代码的情况下,添加新的功能。

这个原则的实现通常依赖于接口和抽象类。通过定义接口或抽象类,我们可以定义一个稳定的API,然后通过继承和实现这些接口或抽象类来添加新的功能。

例如,我们可能有一个PaymentProcessor接口,定义了处理支付的方法。然后,我们可以创建CreditCardPaymentProcessorPaypalPaymentProcessor类来实现这个接口。当我们需要添加一个新的支付方式时,我们只需要创建一个新的类来实现PaymentProcessor接口,而不需要修改现有的代码。

里氏替换原则 (Liskov Substitution Principle, LSP)

里氏替换原则是指如果一个程序使用一个基类的对象,那么它应该能够使用一个子类的对象而不产生任何错误或异常,且不需要修改这个程序的正确性。

这个原则的主要思想是,子类应该能够完全替代它们的基类。这意味着,我们在设计子类时,应该确保它们不会违反基类的行为。

例如,我们可能有一个Rectangle类,有widthheight两个属性,和一个area方法用于计算面积。然后,我们创建了一个Square类继承自Rectangle,并重写了widthheight的setter方法,使得它们总是设置为相同的值。这看起来似乎是合理的,因为在数学上,正方形是一种特殊的矩形。然而,如果我们有一段代码是这样的:

Rectangle r = new Rectangle();
r.setWidth(5);
r.setHeight(4);
assert r.area() == 20;

然后我们用Square替换Rectangle

Rectangle r = new Square();
r.setWidth(5);
r.setHeight(4);
assert r.area() == 20; // 这会失败,因为面积是16,而不是20

我们会发现,尽管SquareRectangle的子类,但它不能完全替代Rectangle。因此,它违反了里氏替换原则。

接口隔离原则 (Interface Segregation Principle, ISP)

接口隔离原则指的是客户端不应该依赖它不需要的接口。换句话说,一个类不应该被强制实现它不需要的方法。这个原则鼓励我们创建精细粒度的接口,而不是创建大而全的接口。

例如,我们可能有一个Worker接口,定义了workeat两个方法。然后,我们有一个Robot类实现了这个接口。然而,Robot并不需要吃东西,所以eat方法对它来说是没有意义的。这就违反了接口隔离原则。

为了遵循接口隔离原则,我们可以将Worker接口拆分为两个接口:WorkableEatableWorkable接口定义了work方法,Eatable接口定义了eat方法。然后,Robot只需要实现Workable接口,而不需要实现Eatable接口。

依赖反转原则 (Dependency Inversion Principle, DIP)

依赖反转原则是指高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。简单来说,要依赖于抽象(接口或抽象类),不要依赖于具体类。

这个原则的主要思想是,我们应该尽可能地使我们的代码解耦。当我们的代码依赖于具体的实现时,它就会变得脆弱且难以改变。然而,当我们的代码依赖于抽象时,我们就可以很容易地更换不同的实现,而不需要修改依赖于这些抽象的代码。

例如,我们可能有一个UserRepository类,它负责从数据库中获取用户。然后,我们有一个UserService类,它依赖于UserRepository来获取用户。这样,当我们需要从不同的数据源获取用户时(比如从网络或内存),我们就需要修改UserService类。然而,如果UserService依赖于一个抽象的UserRepository接口,那么我们就可以通过创建新的UserRepository实现来更换数据源,而不需要修改UserService类。

合成复用原则 (Composition Over Inheritance, COI)

合成复用原则是指尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的。这个原则的主要思想是,组合和聚合可以提供更大的灵活性,降低类与类之间的耦合度,一个类的变动对其他类造成的影响相对较少。

例如,我们可能有一个Bird类和一个Airplane类,它们都需要飞行的功能。我们可以创建一个Flyable接口,然后让BirdAirplane都实现这个接口。这样,BirdAirplane就可以复用Flyable接口的飞行功能,而不需要通过继承来复用这个功能。

迪米特法则 (Law of Demeter, LoD)

迪米特法则也被称为最少知道原则,它指的是一个对象应该对其他对象有最少的了解。换句话说,一个类应该只和它的直接依赖关系交互,不和远程的类交互。

这个原则的主要思想是,我们应该尽可能地降低类与类之间的耦合度。当一个类知道太多其他类的信息时,它就会变得复杂且难以改变。然而,当一个类只和它的直接依赖关系交互时,它就会变得更加独立且易于理解和维护。

例如,我们可能有一个User类,一个Order类,和一个Product类。User类有一个placeOrder方法,需要使用OrderProduct类。然而,如果placeOrder方法直接操作Product类,那么User类就会知道Product类的太多信息,这就违反了迪米特法则。为了遵循迪米特法则,我们可以让placeOrder方法只接受一个Order对象,然后让Order对象负责处理Product对象。

结语

这些原则并不是铁律,而是一种指导思想,可以帮助我们设计出高质量的面向对象系统。在实际的开发过程中,我们需要根据实际的需求和场景,灵活地运用这些原则。

例如,如果我们正在创建一个非常简单的系统,那么严格遵循SOLID原则可能会导致我们的代码变得过于复杂。在这种情况下,我们可能会选择违反一些原则,以便保持我们的代码简单和易于理解。

另一方面,如果我们正在创建一个需要处理复杂业务逻辑和多变需求的大型系统,那么遵循SOLID原则可以帮助我们设计出更加灵活、可维护、可扩展的系统。在这种情况下,我们可能会选择严格遵循一些SOLID原则。

总的来说,SOLID原则是一种工具,而不是目标。我们应该理解这些原则背后的目的和意义,然后在适当的时候使用它们,而不是盲目地遵循它们。

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

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

相关文章

前端常见的栈溢出报错

什么是栈溢出? 在前端开发中,栈溢出是指JavaScript引擎执行代码时,调用栈(call stack)变得太大,超过了浏览器或JavaScript引擎所分配的栈空间,从而导致栈溢出错误。调用栈是一种数据结构&#x…

spring中拦截器Interceptor

目录 什么拦截器? 拦截器的基本使用 注册拦截器中的路径配置 拦截器的执行流程 什么拦截器? 拦截器的基本使用 1.定义拦截器,实现Handlerlnterceptor接口,重写方法 (Ctrl 加 o 选择重写的方法) Component/…

如何实现任意设备远程SSH访问Deepin操作系统【内网穿透】

文章目录 推荐前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击跳…

线性表的链式表示【单链表】

单链表的优缺点 优点缺点 1. 插入和删除操作不需要移动元素,只需要修改指针 2. 不需要大量的连续存储空间 1. 单链表附加指针域,也存在浪费存储空间的缺点。 2. 查找操作需要从表头开始遍历,依次查找,不能随机存取。 单链表结…

day39_mysql

今日内容 0 复习昨日 1 DML 2 约束 3 DQL 0 复习昨日 1 什么是数据库(Database)? 用来组织,存储,管理数据的仓库 2 什么是数据库管理系统(Database Management System-DBMS)? 用来管理数据库的一个软件 3 数据库分类 关系型数据库,Oracle,Mysql,SqlServer,DB2非关系数据库,Re…

Elasticsearch(ES) 下载添加IK分词器

上文 通过Web请求对 Elasticsearch(ES) 进行索引的 增删查 操作 我们通过web请求 创建了一个索引 但 目前 我们的索引是不具有分词效果的 我们并没有为索引指定分词器 所以 我们目前加进去的数据 就会保持原样 没有分词的能力 我们执行get查询操作 会发现一个 mappings字段 它…

v-if及v-for、computed计算属性的使用

v-if 概念及使用 v-if是Vue.js中的一个指令&#xff0c;用于根据表达式的真假值条件性地渲染一块内容。如果表达式的值返回真&#xff0c;则Vue会渲染这块内容&#xff1b;如果返回假&#xff0c;则不渲染。 基本用法: <p v-if"isVisible">看到我了吗&#…

【TI毫米波雷达】CLI模块初始化,demo工程覆写CLI控制指令代码的操作方式(以IWR6843AOP为例)

【TI毫米波雷达】CLI模块初始化&#xff0c;demo工程覆写CLI控制指令代码的操作方式&#xff08;以IWR6843AOP为例&#xff09; 本文主要针对demo工程 通过覆写CLI配置 跳过CLI配置命令 以此来达到自动配置参数 并控制雷达的功能 在此期间不开启CLI和相关初始化 只是针对CLI控…

穿越时空的视觉盛宴:古董展览可视化大屏的魅力

在我们的生活中&#xff0c;科技与传统的交融已经变得无处不在。走进古董的世界&#xff0c;仿佛打开了时光的闸门&#xff0c;每一件古董都承载着千年的故事与历史。然而&#xff0c;传统的古董展览方式&#xff0c;往往受限于空间和展示手段&#xff0c;难以让每一位观众深入…

在CentOS 7 中配置 YUM源

目录 YUM源的功能&#xff1a; YUM 源的安装过程 ps YUM工具 配置YUM仓库/YUM源 网络源&#xff1a;使用官方源 前提&#xff1a;联网 YUM源的功能&#xff1a; YUM&#xff08;Yellowdog Updater Modified&#xff09;是一个在Red Hat、CentOS、Fedora等基于RPM的Linux发…

八种Flink任务监控告警方式

目录 一、Flink应用分析 1.1 Flink任务生命周期 1.2 Flink应用告警视角分析 二、监控告警方案说明 2.1 监控消息队中间件消费者偏移量 2.2 通过调度系统监控Flink任务运行状态 2.3 引入开源服的SDK工具实现 2.4 调用FlinkRestApi实现任务监控告警 2.5 定时去查询目标库…

[网络安全] IIS----WEB服务器

一、 WEB服务器 WEB服务器 也叫网页服务器和 HTTP服务器使用协议: HTTP(端口:80) 或 HTTPS(端口443)浏览器:HTTP客户端网站: 一个或多个网页组成的集合 二、HTTP和HTTPS协议: HTTP : 是 HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09;的简写&#xff0c;…

[数据结构与算法]贪心算法(原理+代码)

博主介绍&#xff1a;✌专研于前后端领域优质创作者、本质互联网精神开源贡献答疑解惑、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战&#xff0c;深受全网粉丝喜爱与支持✌有需要可以联系作者我哦&#xff01; &#x1f447;&#…

HarmonyOS-Stage模型开发概述

Stage模型开发概述 基本概念 下图展示了Stage模型中的基本概念。 图1 Stage模型概念图 UIAbility组件和ExtensionAbility组件 Stage模型提供UIAbility和ExtensionAbility两种类型的组件&#xff0c;这两种组件都有具体的类承载&#xff0c;支持面向对象的开发方式。 UIAbili…

力扣hot100 无重复字符的最长子串 双指针 滑动窗口 哈希

Problem: 3. 无重复字符的最长子串 文章目录 思路Code 思路 &#x1f468;‍&#x1f3eb; 参考 Code ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( 1 ) O(1) O(1) class Solution {public int lengthOfLongestSubstring(String s){if (s null ||…

Quartus生成烧录到FPGA板载Flash的jic文件

简要说明&#xff1a; Altera的FPGA芯片有两种基本分类&#xff0c;一类是纯FPGA&#xff0c;另一类是FPGASoc&#xff08;System on chip)&#xff0c;也就是FPGAHPS&#xff08;Hard Processor System&#xff0c;硬核处理器&#xff09;&#xff0c;对应两种Flash烧录方式&a…

算法模板 2.差分

差分和前缀和是逆运算 差分数组可以将对a数组任意区间的加/减操作优化到O ( 1 ) 一维差分 797. 差分 - AcWing题库 #include <bits/stdc.h> using namespace std; const int N 100010; int a[N], b[N];void insert(int l, int r, int c){b[l] c; //表示l以后&#x…

消息中间件之RocketMQ源码分析(三)

RocketMQ中的Consumer启动流程 RocketMQ客户端中有两个独立的消费者实现类分别为DefaultMQPullConsumer和DefaultMQPushConsumer&#xff0c; DefaultMQPullConsumer DefaultMQPullConsumer,该消费者使用时需要用户主动从Broker中Pull消息和消费消息&#xff0c;提交消费位点…

Altium Designer的学习

PCB设计流程 1.新建空白工程&#xff1a; 创建一个新的工程 新建四个文件&#xff0c;并且保存&#xff1a; 每次打开文件时&#xff0c;打开以.PrjPcb结尾的文件 2.元件符号的创建&#xff1a; 在绘制图形的时候设置成10mil,为了在原理图中显得不那么大。 在绘制引脚的时候设…

外星人入侵(python)

前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件&#xff1a;PyCharm Community Editor 2022 目的&#xff1a;记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置&#xff0c;调用已经封装好的函数方法&#xff0c;一个函数的…