C# 设计模式的六大原则(SOLID)
C# 设计模式的六大原则(SOLID)
引言
在面向对象编程中,设计模式提供了高效、可复用和可维护的代码结构。SOLID原则是软件设计中的一组重要原则,用于确保代码具有良好的可维护性、可扩展性和灵活性。SOLID是五个设计原则的首字母缩写,广泛应用于面向对象编程中,尤其是在大型项目中。
本文将详细介绍SOLID五大设计原则以及它们在C#中的应用,并进一步探讨有时被扩展为“六大原则”的情况。
1. 单一职责原则(SRP)
定义:
单一职责原则(Single Responsibility Principle)规定一个类应该只有一个职责,并且该类应该只有一个引起它变化的原因。也就是说,一个类不应该承担过多的责任,否则会变得难以维护和扩展。
在C#中的实现:
public class OrderProcessor
{public void ProcessOrder(Order order){// 处理订单逻辑}
}public class OrderPrinter
{public void PrintOrder(Order order){// 打印订单逻辑}
}
解释:
在这个例子中,OrderProcessor
类只负责处理订单,而 OrderPrinter
类只负责打印订单。通过分离不同的职责,使得每个类的功能更加专一、简洁。
优势:
- 提高可维护性:更改一个类的逻辑时,不会影响其他无关的部分。
- 增强可测试性:由于职责明确,单元测试变得更加简单。
2. 开闭原则(OCP)
定义:
开闭原则(Open/Closed Principle)表明,“软件实体(类、模块、函数等)应该对扩展开放,对修改封闭”。这意味着当需求变化时,我们应该通过添加新代码来扩展系统,而不是修改现有代码。
在C#中的实现:
public interface IPaymentMethod
{void Pay();
}public class CreditCardPayment : IPaymentMethod
{public void Pay() { /* 支付实现 */ }
}public class PayPalPayment : IPaymentMethod
{public void Pay() { /* 支付实现 */ }
}public class PaymentProcessor
{public void ProcessPayment(IPaymentMethod paymentMethod){paymentMethod.Pay();}
}
解释:
通过使用接口(IPaymentMethod
),我们可以为不同的支付方式实现扩展。增加新的支付方式时,我们只需创建新的实现类,而不需要修改 PaymentProcessor
类。
优势:
- 灵活性:新功能可以通过增加新类而不破坏现有系统的稳定性。
- 增强可扩展性:能够适应系统需求的变化,而无需修改已有的代码。
3. 里氏替换原则(LSP)
定义:
里氏替换原则(Liskov Substitution Principle)规定,子类对象应该能够替换父类对象,并且不会改变程序的正确性。也就是说,子类必须遵循父类的行为约定,并可以在任何父类对象出现的地方替代父类。
在C#中的实现:
public class Bird
{public virtual void Fly() { /* 通用飞行实现 */ }
}public class Sparrow : Bird
{public override void Fly() { /* 麻雀飞行实现 */ }
}public class Penguin : Bird
{public override void Fly(){throw new NotSupportedException("企鹅不能飞");}
}
解释:
在上面的代码中,Penguin
类违反了里氏替换原则,因为企鹅不能飞,强制让其实现 Fly
方法不符合实际需求。我们可以通过接口或其他设计方式来避免这种问题。
优势:
- 增强代码的可替换性:子类应该能无缝替换父类,确保系统的健壮性。
- 减少代码错误:遵循该原则避免不必要的设计冲突。
4. 接口隔离原则(ISP)
定义:
接口隔离原则(Interface Segregation Principle)要求类应该仅实现它需要使用的接口,而不应该强迫它实现不需要的方法。换句话说,接口应该细化,而不是做一个“臃肿”的接口。
在C#中的实现:
public interface IPrinter
{void Print();
}public interface IFax
{void Fax();
}public class MultiFunctionMachine : IPrinter, IFax
{public void Print() { /* 打印实现 */ }public void Fax() { /* 传真实现 */ }
}public class Printer : IPrinter
{public void Print() { /* 打印实现 */ }
}
解释:
在这个例子中,Printer
类只实现了与打印相关的接口,而 MultiFunctionMachine
类同时实现了打印和传真接口。根据接口隔离原则,如果一个类只关心打印,那么它不应该实现传真接口。
优势:
- 减少不必要的依赖:减少类与类之间的不必要耦合。
- 增强代码灵活性:提高代码的复用性,减少修改的影响范围。
5. 依赖倒转原则(DIP)
定义:
依赖倒转原则(Dependency Inversion Principle)要求高层模块不应该依赖低层模块,而应该依赖抽象。具体来说,应该依赖接口或抽象类,而不是具体的实现类。
在C#中的实现:
public interface IDatabase
{void SaveData();
}public class SQLServerDatabase : IDatabase
{public void SaveData() { /* SQL Server 数据库实现 */ }
}public class BusinessLogic
{private readonly IDatabase _database;public BusinessLogic(IDatabase database){_database = database;}public void ProcessData() { _database.SaveData(); }
}
解释:
在这个例子中,BusinessLogic
类依赖于 IDatabase
接口,而不是具体的 SQLServerDatabase
类。通过这种方式,我们可以轻松地将不同的数据库实现替换到 BusinessLogic
中。
优势:
- 提高模块的灵活性:减少模块之间的耦合,增强可扩展性。
- 便于单元测试:可以使用模拟对象(mock)轻松替换数据库实现,进行单元测试。
6. 总结
SOLID原则是现代面向对象设计中的基石,帮助开发人员编写高效、可维护、可扩展的代码。通过遵循这些原则,可以极大提高系统的质量、可读性和可测试性。在实际开发中,理解和应用SOLID原则对于构建稳定和高质量的应用程序至关重要。
希望这篇博客能够帮助你更好地理解并应用SOLID原则。如果你有任何问题,欢迎在评论区讨论或者留言交流!
相关文章:

C# 设计模式的六大原则(SOLID)
C# 设计模式的六大原则(SOLID) 引言 在面向对象编程中,设计模式提供了高效、可复用和可维护的代码结构。SOLID原则是软件设计中的一组重要原则,用于确保代码具有良好的可维护性、可扩展性和灵活性。SOLID是五个设计原则的首字母…...

数据库自增 id 过大导致前端时数据丢失
可以看到,前端响应参数是没有丢失精度的 但是在接受 axios 请求参数时出现了精度丢失 解决方案一:改变 axios 字符编码 axios.defaults.headers[Content-Type] application/json;charsetUTF-8; 未解决 解决方案二:手动使用 json.parse() …...

第二十六天 自然语言处理(NLP)词嵌入(Word2Vec、GloVe)
自然语言处理(NLP)中的词嵌入(Word2Vec、GloVe)技术,是NLP领域的重要组成部分,它们为词汇提供了高维空间到低维向量的映射,使得语义相似的词汇在向量空间中的距离更近。以下是对这些技术的详细解…...

MongoDB 固定集合
MongoDB 固定集合 MongoDB中的固定集合(Capped Collections)是一种具有固定大小的集合,当集合中的数据达到其最大大小时,它会自动覆盖最早的文档。这种类型的集合在MongoDB中用于实现高效的、固定大小的循环缓冲区。本文将详细介…...

数据结构9.3 - 文件基础(C++)
目录 1 打开文件字符读写关闭文件 上图源自:https://blog.csdn.net/LG1259156776/article/details/47035583 1 打开文件 法 1法 2ofstream file(path);ofstream file;file.open(path); #include<bits/stdc.h> using namespace std;int main() {char path[]…...

Leetcode 1254 Number of Closed Islands + Leetcode 1020 Number of Enclaves
Leetcode 1254 题意 给定一个m*n的矩阵含有0和1,1代表水,0代表陆地,岛屿是陆地的集合,如果一个岛屿和四个方向的边界相连,则不算封闭岛屿。求有多少个封闭的岛屿。 题目链接 https://leetcode.com/problems/number…...

Junit4单元测试快速上手
文章目录 POM依赖引入业务层测试代码Web层测试代码生成测试类文件 在工作中我用的最多的单元测试框架是Junit4。通常在写DAO、Service、Web层代码的时候都会进行单元测试,方便后续编码,前端甩锅。 POM依赖引入 <dependency><groupId>org.spr…...

U盘提示格式化?原因、恢复方案与预防措施全解析
一、U盘提示格式化现象概述 在日常使用U盘的过程中,我们有时会遇到一个令人头疼的问题——U盘插入电脑后,系统却弹出一个提示框,告知我们U盘需要格式化才能访问。这个提示往往伴随着数据的潜在丢失风险,让我们不禁为之心焦。U盘提…...

HTML——13.超链接
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>超链接</title></head><body><!--超链接:从一个网页链接到另一个网页--><!--语法:<a href"淘宝网链接的地址"> 淘宝…...

vue中的设计模式
vue中使用了哪些设计模式 1. 观察者模式(Observer Pattern) 应用场景:Vue 的响应式系统核心就是观察者模式。 实现方式:通过 Object.defineProperty 或 Proxy 监听数据变化,当数据发生变化时,通知依赖的视…...

利用python将图片转换为pdf格式的多种方法,实现批量转换,内置模板代码,全网最全,超详细!!!
文章目录 前言1、img2pdf库的使用1.1 安装img2pdf库1.2 案例演示(模板代码) 2、Pillow库的使用2.1 pillow库的安装2.2 案例演示(模板代码) 3、PyMuPDF库的使用3.1 安装pymupdf库3.2 案例演示(模板代码)3.3 …...

tcpdump的常见方法
详解tcpdump的使用方法:网络数据包捕获与分析 tcpdump是一个功能强大的命令行工具,用于捕获和分析通过网络接口传输的数据包。它广泛应用于网络故障诊断、网络安全监控和协议分析等领域。本文将详细介绍tcpdump的使用方法,包括安装、基本命令…...

工控主板ESM7000/6800E支持远程桌面控制
英创公司ESM7000 是面向工业领域的双核 Cortex-A7 高性能嵌入式主板,ESM6800E则为单核Cortex-A7 高性价比嵌入式主板,ESM7000、ESM6800E都是公司的成熟产品,已广泛应用于工业很多领域。ESM7000/6800E板卡中Linux系统配置为linux-4.9.11内核、…...

wamp php7.4 运行dm8
背景 1、电脑安装了dm8,具体参照官网dm8安装 2、安装好了wamp,我当前的php版本切换成了7.4的,我wamp的安装路径d:\wamp64\ 操作 3、查看phpinfo,如果Thread Safet为enabled,则选择pdo74_dm.dll,否则选择…...

HTML5 进度条(Progress Bar)详解
HTML5 进度条(Progress Bar)详解 进度条是用于显示任务完成进度的控件,常用于加载、上传或下载等操作。HTML5提供了原生的<progress>元素,使得创建进度条变得简单和直观。 1. 基本用法 <progress>元素的基本语法如…...

LabVIEW开发中常见硬件通讯接口快速识别
在 LabVIEW 开发中,与硬件进行通讯是实现数据采集与控制的重要环节。准确判断通讯接口类型和协议,可以提高开发效率,减少调试时间。本文结合 LabVIEW 的实际应用,详细介绍如何识别和判断常见硬件通讯接口的定义,并提供…...

高频 SQL 50 题(基础版)_1068. 产品销售分析 I
销售表 Sales: (sale_id, year) 是销售表 Sales 的主键(具有唯一值的列的组合)。 product_id 是关联到产品表 Product 的外键(reference 列)。 该表的每一行显示 product_id 在某一年的销售情况。 注意: price 表示每…...

笔记:一次mysql主从复制延迟高的处理尝试
背景 mysql 5.7 主从复制 主库进行了一次灌数,导致多个大事务产生,主从延迟下不去,经确认该表最终truncate,并且该表仅有insert和select操作,故对该表的事务进行跳过,直到同步至truncate 跳过事务需谨慎&…...

基于C语言的卡丁车管理系统【控制台应用程序】
注意:需要提前创建对应的.dat文件 本项目实现了数据的永久存储,有用户的注册、登录。 管理员对卡丁车的管理、查看预约用户、修改帐户权限。 用户对个人信息的管理、查看并预约卡丁车、卡丁车维修上报。 维修员对卡丁车的维修状态上报、个人信息管理。 …...

Docker 搭建 Gogs
Docker 搭建 Gogs 准备工作 先准备配置目录和持久化目录,举个栗子:mkdir -p /opt/module/gogs/{data,backup} 拉取官方Gogs镜像 # 拉取 gogs:0.13 docker pull gogs/gogs:0.13 # 拉取最新版 gogs 镜像 docker pull gogs/gogs启动一个临时容器【通过创…...

PostgreSQL的备份方式
PostgreSQL 提供多种方式进行备份,适用于不同需求的场景。常用的备份方法如下: 1. 逻辑备份(pg_dump 和 pg_dumpall) 1.1 使用 pg_dump 备份单个数据库 pg_dump 是 PostgreSQL 内置的逻辑备份工具,可以将数据库导出为…...

Springboot 3项目整合Knife4j接口文档(接口分组详细教程)
文章目录 前言一、Spring Boot 3.0整合Knife4j二、OpenApi 3注解的使用规范三、使用步骤 1.Spring Boot 3.0项目中使用knife4j2.在application.yml中添加knife4j相关配置3.设置WebMvc相关配置(解决封装统一异常处理后doc.html无法打开的问题)4.创建Knif…...

深入解析 Conda 安装的默认依赖包及其作用:conda create安装了哪些包(中英双语)
深入解析 Conda 安装的默认依赖包及其作用 当我们使用 Conda 创建新环境时,例如执行命令: conda create -n olmes python3.10Conda 会自动为我们安装一系列基础依赖包,保证 Python 环境能够正常运行。这些包不仅是我们开发的基础工具&#…...

Redis核心技术知识点全集
Redis数据结构和常用命令 1. String字符串2. Hash哈希3. List列表4. Set集合5. Sorted Set有序集合6. Redis常用命令参考Redis事务机制...

【Unity3D】ECS入门学习(九)SystemBase
SystemBase:支持主线程或多线程执行筛选实体任务。 主要介绍是内部成员:Entities的各种筛选方法,其内部成员还有EntityManager ForEach方法筛选,传递一个有参委托函数进去,参数ref xxx组件类(可填多个&…...

【Triton-ONNX】如何使用 ONNX 模型服务与 Triton 通信执行推理任务上-Triton快速开始
模型部署系列文章 前置-docker 理解:【 0 基础 Docker 极速入门】镜像、容器、常用命令总结前置-http/gRPC 的理解: 【HTTP和gRPC的区别】协议类型/传输效率 /性能等对比【保姆级教程附代码】Pytorch (.pth) 到 TensorRT (.plan) 模型转化全流程【保姆级教程附代码(二)】Pytor…...

CertiK《Hack3d:2024年度安全报告》(附报告全文链接)
CertiK《Hack3d:2024年度安全报告》现已发布,本次报告深入分析了2024年Web3.0领域的安全状况。2024年损失总额超过23亿美元,同比增幅高达31.61%;其中,12月的损失金额最少。过去一年,网络钓鱼攻击和私钥泄露…...

TIOBE 指数 12 月排行榜公布,VB.Net排行第九
IT之家 12 月 10 日消息,TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标,评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎,今天 TIOBE 官网公布了 2024 年 12 月的编程语言排行榜,IT之家整理如下: …...

【网络协议】开放式最短路径优先协议OSPF详解(一)
OSPF 是为取代 RIP 而开发的一种无类别的链路状态路由协议,它通过使用区域划分以实现更好的可扩展性。 文章目录 链路状态路由协议OSPF 的工作原理OSPF 数据包类型Dijkstra算法、管理距离与度量值OSPF的管理距离OSPF的度量值 链路状态路由协议的优势拓扑结构路由器O…...

嵌入式Linux驱动开发的基本知识(驱动程序的本质、常见的设备类型、设备号的本质理解、设备实例的注册过程)
基本概念之什么是驱动程序()? 驱动程序本质上是代码逻辑的集合,通常用于管理、驱动多个设备实例。某个设备要想使用驱动程序,需要实例化相应的驱动程序的结构体,并在系统中注册,获得主设备号、次设备号,并…...