C#的五大设计原则-solid原则

什么是C#的五大设计原则,我们用人话来解释一下,希望小伙伴们能学会:

好的,让我们以一种幽默的方式来解释C#的五大设计原则(SOLID):

单一职责原则(Single Responsibility Principle, SRP):别让一个类做得像瑞士军刀一样样样都干,它会累趴下的。让每个类专注于一件事,成就一个小专家!

开闭原则(Open/Closed Principle, OCP):代码就像房子一样,应该允许你随时装修,但不要让你每次都得拆墙。你的类应该开放给扩展,关闭给修改。装修可以,但别动地基。

里氏替换原则(Liskov Substitution Principle, LSP):如果它看起来像鸭子,游起来像鸭子,叫起来也像鸭子,那它就应该是个鸭子。子类应该能完全替代父类,就像鸭子替代鸭子一样。

接口隔离原则(Interface Segregation Principle, ISP):不要逼用户点一堆不想要的菜,分开菜单让他们点自己喜欢的。让接口精简,用户用起来才不会吐槽你。

依赖倒置原则(Dependency Inversion Principle, DIP):别总想着亲自动手干活,雇个专业的帮你干!高层模块不应该依赖低层模块,而应该依赖于抽象。让专业的人做专业的事,你只需要指挥就好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1. 单一职责原则(SRP - Single Responsibility Principle)

不使用SRP:

public class UserService
{public void RegisterUser(string name, string email){// 保存用户到数据库SaveUserToDatabase(name, email);// 发送欢迎邮件SendWelcomeEmail(email);}private void SaveUserToDatabase(string name, string email){// 代码逻辑}private void SendWelcomeEmail(string email){// 代码逻辑}
}

在这个示例中,UserService类同时处理用户注册和发送邮件,职责不单一,导致类的复杂性增加,不利于维护和扩展。

使用SRP:

public class User
{public string Name { get; set; }public string Email { get; set; }
}public class UserRepository
{public void AddUser(User user) { /* 代码 */ }public User GetUserByEmail(string email) { /* 代码 */ }
}public class EmailService
{public void SendEmail(User user) { /* 代码 */ }
}public class UserService
{private readonly UserRepository _userRepository;private readonly EmailService _emailService;public UserService(UserRepository userRepository, EmailService emailService){_userRepository = userRepository;_emailService = emailService;}public void RegisterUser(User user){_userRepository.AddUser(user);_emailService.SendEmail(user);}
}

在这个示例中,职责被分离到了不同的类中,UserService只负责协调这些操作,使代码更清晰、可维护。

2. 开闭原则(OCP - Open/Closed Principle)

不使用OCP:

public class Shape
{public double Radius { get; set; }public double Width { get; set; }public double Height { get; set; }public double GetArea(string shapeType){if (shapeType == "Circle"){return Math.PI * Radius * Radius;}else if (shapeType == "Rectangle"){return Width * Height;}else{return 0;}}
}

在这个示例中,添加新的形状类型需要修改GetArea方法的代码,违反了开闭原则。

使用OCP:

public abstract class Shape
{public abstract double Area();
}public class Circle : Shape
{public double Radius { get; set; }public override double Area() => Math.PI * Radius * Radius;
}public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override double Area() => Width * Height;
}

在这个示例中,通过扩展Shape类,我们可以添加新的形状而不需要修改现有的代码,符合开闭原则。

3. 里氏替换原则(LSP - Liskov Substitution Principle)

不使用LSP:

public class Rectangle
{public virtual double Width { get; set; }public virtual double Height { get; set; }public double Area() => Width * Height;
}public class Square : Rectangle
{public override double Width{set { base.Width = base.Height = value; }}public override double Height{set { base.Width = base.Height = value; }}
}

在这个示例中,Square类违反了里氏替换原则,因为WidthHeight的行为在子类中改变了。

使用LSP:

public abstract class Shape
{public abstract double Area();
}public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override double Area() => Width * Height;
}public class Square : Shape
{public double SideLength { get; set; }public override double Area() => SideLength * SideLength;
}

在这个示例中,RectangleSquare都正确实现了ShapeArea方法,符合里氏替换原则。

4. 接口隔离原则(ISP - Interface Segregation Principle)

不使用ISP:

public interface IWorker
{void Work();void Eat();
}public class Worker : IWorker
{public void Work() { /* 代码逻辑 */ }public void Eat() { /* 代码逻辑 */ }
}public class Robot : IWorker
{public void Work() { /* 代码逻辑 */ }public void Eat(){throw new NotImplementedException();}
}

在这个示例中,Robot类必须实现它不需要的Eat方法,导致接口不符合实际需求。

使用ISP:

public interface IWorkable
{void Work();
}public interface IEatable
{void Eat();
}public class Worker : IWorkable, IEatable
{public void Work() { /* 代码逻辑 */ }public void Eat() { /* 代码逻辑 */ }
}public class Robot : IWorkable
{public void Work() { /* 代码逻辑 */ }
}

在这个示例中,IWorkableIEatable接口被分离,Robot类只实现了需要的接口,符合接口隔离原则。

5. 依赖倒置原则(DIP - Dependency Inversion Principle)

不使用DIP:

public class DatabaseLogger
{public void Log(string message){// 记录日志到数据库}
}public class UserService
{private readonly DatabaseLogger _logger = new DatabaseLogger();public void RegisterUser(string name, string email){// 记录日志_logger.Log("Registering user " + name);// 其他代码}
}

在这个示例中,UserService类直接依赖于具体的DatabaseLogger实现,违反了依赖倒置原则。

使用DIP:

public interface ILogger
{void Log(string message);
}public class DatabaseLogger : ILogger
{public void Log(string message){// 记录日志到数据库}
}public class FileLogger : ILogger
{public void Log(string message){// 记录日志到文件}
}public class UserService
{private readonly ILogger _logger;public UserService(ILogger logger){_logger = logger;}public void RegisterUser(string name, string email){// 记录日志_logger.Log("Registering user " + name);// 其他代码}
}

在这个示例中,UserService类依赖于ILogger接口,而不是具体的实现,符合依赖倒置原则,使得代码更加灵活和可扩展。

总结对比

  • 单一职责原则(SRP): 通过分离职责减少类的复杂度,使代码更易读和维护。不使用SRP会导致类变得庞大,职责不清,维护困难。
  • 开闭原则(OCP): 通过扩展来增加新功能,而不是修改已有代码,提高了代码的稳定性和可扩展性。不使用OCP会导致每次增加新功能都需要修改已有代码,增加了出错的风险。
  • 里氏替换原则(LSP): 确保子类可以替代基类而不会导致程序出错,保证继承的正确性。不使用LSP会导致子类行为不一致,破坏程序的稳定性。
  • 接口隔离原则(ISP): 通过细化接口,使得类只依赖于需要的接口,减少不必要的依赖关系。不使用ISP会导致类实现不需要的接口方法,增加了代码的复杂度。
  • 依赖倒置原则(DIP): 通过依赖于抽象(接口或抽象类)而不是具体实现,降低模块之间的耦合,提高代码的灵活性和可测试性。不使用DIP会导致类之间的高耦合,难以进行单元测试和模块替换。

通过遵循SOLID原则,可以显著提高代码的可维护性、可扩展性和灵活性,使开发和维护变得更加高效。

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

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

相关文章

通过容器启动QAnything知识库问答系统

QAnything (Question and Answer based on Anything) 是致力于支持任意格式文件或数据库的本地知识库问答系统,可断网安装使用。目前已支持格式:PDF(pdf),Word(docx),PPT(pptx),XLS(xlsx),Markdown(md)&…

2024年教育政策与实践研讨会(ICEPP 2024)

随着全球化的不断深入,教育作为国家发展的基石,其政策与实践的探讨愈发显得重要。为此,备受瞩目的教育政策与实践研讨会(ICEPP 2024)将于2024年11月8日至10日在中国武汉隆重举行。此次会议汇聚了国内外众多专家学者&am…

浅谈k8s中cni0和docker0的关系和区别

最近在复习k8s网络方面的知识,查看之前学习时整理的笔记和文档还有过往自己总结的博客之后发现一个问题,就是在有关flannel和calico这两个k8s网络插件的文章和博客中,会涉及到cni0和docker0这两个网桥设备,但是都没有明确说明他们…

AI教育行业全景图(最新版);AI时代内容创作者的窘境;2年内AI教育赛道的切入机会;可汗学院创始人「AI教育革命」新书问世 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 1. 可汗学院 (Khan Academy) 创始人新书发布:AI将如何颠覆传统教育 可汗学院(Khan Academy)是 Salman Khan 创立的…

LabVIEW项目外协时选择公司与个人兼职的比较

​在选择LabVIEW项目外协合作伙伴时,外协公司和个人兼职各有优劣。个人兼职成本较低且灵活,但在可靠性、技术覆盖面、资源和风险管理上存在不足。而外协公司拥有专业团队、丰富资源、完善的项目管理和风险控制,尽管成本较高,但能提…

分享一款Type C接口USB转2路485模块【带完整原理图】

大家好,我是『芯知识学堂』的SingleYork,今天给大家分享一款很实用的工具–基于Type C接口的USB转2路485模块。 这款模块主芯片采用南京沁恒的CH342F这款芯片,芯片特性如下: 该系列芯片有QFN24和ESSOP10 这2种封装,…

leetcode-20-回溯-切割、子集

一、[131]分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ] 分析&…

Steam页面打不开?steam显示当前游戏不可用是怎么回事

Steam是全球最大的游戏综合发行平台,每年为无数玩家呈现了多款精彩游戏,不过由于网络问题或其他异常因素影响,有很多玩家会在访问steam或steam的游戏商品页时,遇到Steam提示当前游戏在您平台不可用、打不开游戏页面的情况&#xf…

PCL 点云最小图割(前景、背景点云提取)

点云最小图割 一、概述1.1 概念1.2 算法原理二、代码示例三、运行结果🙋 结果预览 一、概述 1.1 概念 最小图割算法(pcl::MinCutSegmentation):是一种基于图论的对象分割方法,主要用于点云数据的处理和分析。该算法将点云数据表示为一个图结构,其中点云中的点作为图的节…

自然语言处理——英文文本预处理

高质量数据的重要性 数据的质量直接影响模型的性能和准确性。高质量的数据可以显著提升模型的学习效果,帮助模型更准确地识别模式、进行预测和决策。具体原因包括以下几点: 噪音减少:高质量的数据经过清理,减少了无关或错误信息…

【揭秘】国内十大顶尖AI大模型,引领智能科技新纪元

大模型大模型通常指的是参数量非常大、数据量也非常大的深度学习模型。这些模型由数百万到数十亿甚至更多的参数组成,需要海量的数据和强大的计算资源进行训练和推理学习的模型。大模型设计的目的在于提高模型的表示能力和性能、应对复杂数据集和任务、提升泛化能力…

家政小程序的开发,带动市场快速发展,提高家政服务质量

当下生活水平逐渐提高,也增加了年轻人的工作压力,同时老龄化也在日益增加,使得大众对家政的需求日益提高,能力、服务质量高的家政人员能够有效提高大众的生活幸福指数。 但是,传统的家政服务模式存在着效率低、用户与…

Qt的学习之路

目录 一、信号槽机制 1.1 基本概念 1.2 特点 1.3 使用方法 1.4 信号槽连接类型 1.5 注意 二、元对象系统 2.1 基本概念 2.2 实现方式 2.3 主要特性 2.4 使用场景 2.5 元对象系统如何识别信号槽 三、国际化 3.1 标记可翻译的文本(tr函数) …

FPGA - DFT(离散傅里叶变换)—FFT(快速傅里叶变化)

一,DFT(离散傅里叶变换原理) 1,DFT(离散傅里叶变换原理)理论简介 在数字信号处理中有一个基本概念: 如果信号在频域是离散的,则该信号在时域就表现为周期性的时间函数;相反,如果信号在时域是离散的&#x…

VMware ESXi 8.0U3 macOS Unlocker OEM BIOS 集成驱动版,新增 12 款 I219 网卡驱动

VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS 集成驱动版,新增 12 款 I219 网卡驱动 比如联想 ThinkStation P3 Tower 板载 Intel Ethernet Connection (22) I219-LM 0x8086 0x0dc7 已受此版本支持。 VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS 集成网…

【ONLYOFFICE】| 桌面编辑器从0-1使用初体验

目录 一. 🦁 写在前面二. 🦁 在线使用感受2.1 创建 ONLYOFFICE 账号2.2 编辑pdf文档2.3 pdf直接创建表格 三. 🦁 写在最后 一. 🦁 写在前面 所谓桌面编辑器就是一种用于编辑文本、图像、视频等多种自媒体的软件工具,具…

llm学习-2(使用embedding和数据处理)

首先可以简单了解一下向量数据库相关知识: 向量数据库相关知识(搬运学习,建议还是看原文,这个只是我自己的学习记录)-CSDN博客 补充: 使用embedding API 文心千帆API Embedding-V1是基于百度文心大模型…

【论文阅读】transformer及其变体

写在前面: transformer模型已经是老生常谈的一个东西,以transformer为基础出现了很多变体和文章,Informer、autoformer、itransformer等等都是顶刊顶会。一提到transformer自然就是注意力机制,变体更是数不胜数,一提到…

huggingface 笔记:peft

1 介绍 PEFT 提供了参数高效的方法来微调大型预训练模型。传统的范式是为每个下游任务微调模型的所有参数,但由于当前模型的参数数量巨大,这变得极其昂贵且不切实际。相反,训练较少数量的提示参数或使用诸如低秩适应 (LoRA) 的重新参数化方法…

和小红书一起参会! 了解大模型与大数据融合的技术趋势

在过去的两年中,“大模型”无疑成为互联网行业的焦点话题,曾经炙手可热的大数据架构似乎淡出公众视野。然而,大数据领域并未停滞不前,反而快速演进,传统依赖众多开源组件的大数据平台正逐步过渡到以融合与简化为核心特…