C#中常见的软件设计模式及应用场景
文章目录
- 前言
- 1、单例模式 (Singleton)
- 1.1 详细说明
- 1.2 应用场景示例
- 2、工厂模式 (Factory Method)
- 2.1 详细说明
- 2.2 应用场景示例
- 3、观察者模式 (Observer)
- 3.1 详细说明
- 3.2 应用场景示例
- 4、策略模式 (Strategy)
- 4.1 详细说明
- 4.2 应用场景示例
- 5、适配器模式 (Adapter)
- 5.1 详细说明
- 5.2 应用场景示例
- 总结
前言
在C#开发中,设计模式是一种被广泛应用的软件设计思想,它可以帮助我们提高代码的可维护性、可扩展性和可复用性。本文将详细介绍C#中几种常见的软件设计模式,并提供每种模式的具体应用场景示例,以展示其在实际项目中的应用效果和益处。
1、单例模式 (Singleton)
1.1 详细说明
单例模式确保一个类只有一个实例,并提供一个全局访问点。这个模式通常用于那些只需要一个实例且频繁使用的对象,例如数据库连接池、日志对象、配置对象等。
1.2 应用场景示例
场景1: 应用程序需要一个全局的配置管理器来管理所有的配置信息。
public class ConfigurationManager
{private static ConfigurationManager _instance;private ConfigurationManager(){// 初始化配置}public static ConfigurationManager Instance{get{if (_instance == null){_instance = new ConfigurationManager();}return _instance;}}// 配置操作方法
}
场景2: 在一个多线程的环境下,需要确保某个资源只被创建一次并在全局范围内访问。比如数据库连接池的实现。
public class Singleton
{private static Singleton instance;private static readonly object lockObject = new object();private Singleton() { }public static Singleton Instance{get{lock (lockObject){if (instance == null){instance = new Singleton();}}return instance;}}
}
2、工厂模式 (Factory Method)
2.1 详细说明
工厂模式定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类中进行。
2.2 应用场景示例
场景: 应用程序需要根据用户的选择创建不同类型的图形对象(如圆形、矩形)。
public interface IGraphic
{void Draw();
}public class Circle : IGraphic
{public void Draw(){Console.WriteLine("Drawing a circle");}
}public class Rectangle : IGraphic
{public void Draw(){Console.WriteLine("Drawing a rectangle");}
}public abstract class Factory
{public abstract IGraphic CreateGraphic(string type);
}public class CircleFactory : Factory
{public override IGraphic CreateGraphic(string type){return new Circle();}
}public class RectangleFactory : Factory
{public override IGraphic CreateGraphic(string type){return new Rectangle();}
}// 使用
IFactory factory = new CircleFactory();
IGraphic graphic = factory.CreateGraphic("Circle");
graphic.Draw(); // 输出: Drawing a circle
3、观察者模式 (Observer)
3.1 详细说明
观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并自动更新。
3.2 应用场景示例
场景1: 股票市场应用程序中,当股票价格发生变化时,需要通知所有订阅了该股票的投资者。
public interface IObserver
{void Update(float stockPrice);
}public interface ISubject
{void Attach(IObserver observer);void Detach(IObserver observer);void Notify();
}public class StockMarket : ISubject
{private List<IObserver> observers = new List<IObserver>();private float stockPrice;public void Attach(IObserver observer){observers.Add(observer);}public void Detach(IObserver observer){observers.Remove(observer);}public void Notify(){foreach (var observer in observers){observer.Update(stockPrice);}}public void SetStockPrice(float price){stockPrice = price;Notify();}
}public class Investor : IObserver
{public void Update(float stockPrice){Console.WriteLine($"Stock price updated to: {stockPrice}");}
}// 使用
StockMarket stockMarket = new StockMarket();
Investor investor1 = new Investor();
Investor investor2 = new Investor();stockMarket.Attach(investor1);
stockMarket.Attach(investor2);stockMarket.SetStockPrice(100.0f); // 两个投资者都将收到通知
场景2: 在一个新闻发布订阅系统中,当有新的新闻发布时,订阅者可以自动收到通知并显示最新的新闻内容。
public interface IObserver
{void Update(string news);
}public interface ISubject
{void Attach(IObserver observer);void Detach(IObserver observer);void Notify(string news);
}public class NewsPublisher : ISubject
{private List<IObserver> observers = new List<IObserver>();private string news;public void Attach(IObserver observer){observers.Add(observer);}public void Detach(IObserver observer){observers.Remove(observer);}public void Notify(string news){this.news = news;foreach (var observer in observers){observer.Update(news);}}
}public class NewsSubscriber : IObserver
{private string name;public NewsSubscriber(string name){this.name = name;}public void Update(string news){Console.WriteLine($"{name} received news: {news}");}
}
4、策略模式 (Strategy)
4.1 详细说明
策略模式定义了一系列算法,并将每一个算法封装起来,以便它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。
4.2 应用场景示例
场景: 一个文本编辑器需要支持多种格式的文件保存方式(如纯文本、HTML、Markdown等)。
public abstract class FileSaverStrategy
{public abstract void Save(string content, string filePath);
}public class TextFileSaver : FileSaverStrategy
{public override void Save(string content, string filePath){using (StreamWriter sw = File.CreateText(filePath)){sw.Write(content);}}
}public class HtmlFileSaver : FileSaverStrategy
{public override void Save(string content, string filePath){// HTML 保存逻辑}
}public class MarkdownFileSaver : FileSaverStrategy
{public override void Save(string content, string filePath){// Markdown 保存逻辑}
}public class Document
{private FileSaverStrategy saver;public void SetSaver(FileSaverStrategy saver){this.saver = saver;}public void SaveDocument(string content, string filePath){saver.Save(content, filePath);}
}// 使用
Document document = new Document();
document.SetSaver(new TextFileSaver());
document.SaveDocument("Hello, World!", "hello.txt");// later on, if we want to save as HTML
document.SetSaver(new HtmlFileSaver());
document.SaveDocument("<p>Hello, World!</p>", "hello.html");
5、适配器模式 (Adapter)
5.1 详细说明
适配器模式将一个类的接口转换成客户端期望的另一个接口。适配器模式让原本接口不兼容的类可以一起工作。
5.2 应用场景示例
场景: 有一个旧式的音乐播放器,只能播放MP3格式的音乐,但现在需要播放MP4格式的音乐。
public interface IMusicPlayer
{void Play(string fileExtension);
}public class Mp3MusicPlayer : IMusicPlayer
{public void Play(string fileExtension){if (fileExtension == "mp3"){Console.WriteLine("Playing MP3 music");}}
}public class Mp4MusicPlayer : IMusicPlayer
{public void Play(string fileExtension){if (fileExtension == "mp4"){Console.WriteLine("Playing MP4 music");}}
}public class Mp4ToMp3Adapter : IMusicPlayer
{private Mp4MusicPlayer mp4Player;public Mp4ToMp3Adapter(Mp4MusicPlayer mp4Player){this.mp4Player = mp4Player;}public void Play(string fileExtension){if (fileExtension == "mp3"){// 将MP4音乐转换为MP3音乐mp4Player.Play("mp4");}}
}// 使用
IMusicPlayer musicPlayer = new Mp3MusicPlayer();
musicPlayer.Play("mp3"); // 输出:Playing MP3 musicmusicPlayer = new Mp4ToMp3Adapter(new Mp4MusicPlayer());
musicPlayer.Play("mp3"); // 输出:Playing MP4 music(通过适配器转换)
总结
通过使用这些常见的设计模式,我们可以更好地组织和管理代码,提高代码的可读性、可维护性和可扩展性。每个设计模式都有其独特的应用场景和优势,在实际项目中灵活运用可以有效解决各种问题。希望本文能够帮助读者理解C#设计模式的多样性,并在实践中加以应用。
相关文章:
C#中常见的软件设计模式及应用场景
文章目录 前言1、单例模式 (Singleton)1.1 详细说明1.2 应用场景示例 2、工厂模式 (Factory Method)2.1 详细说明2.2 应用场景示例 3、观察者模式 (Observer)3.1 详细说明3.2 应用场景示例 4、策略模式 (Strategy)4.1 详细说明4.2 应用场景示例 5、适配器模式 (Adapter)5.1 详细…...
字符串相关函数和文件操作
文章目录 1. C/C 字符串概述1.1 字符串常量1.2 字符数组 2. 字符串函数2.1 拷贝赋值功能相关函数(覆盖)2.1.1 strcpy2.1.2 strncpy2.1.3 memcpy2.1.4 memmove2.1.5 memset2.1.6 注意小点2.1.7 【函数区别】 2.2 追加功能相关函数2.2.1 strcat2.2.2 strnc…...
【c++学习】数据结构中的栈
c栈 栈代码用线性表实现栈用链表实现栈 栈 栈:先进后出 只对栈顶元素进行操作,包括新元素入栈、栈顶元素出栈和查看栈顶元素(只支持对栈顶的增、删、查)。 代码 下述代码实现了栈及其接口 包括对栈顶的增、删、查以及查看栈的大…...
新建react项目,react-router-dom配置路由,引入antd
提示:reactrouter6.4版本,与reactrouter5.0的版本用法有区别,互不兼容需注意 文章目录 前言一、创建项目二、新建文件并引入react-router-dom、antd三、配置路由跳转四、效果五、遇到的问题六、参考文档总结 前言 需求:新建react项…...
Transformer and Pretrain Language Models3-6
Pretrain Language Models预训练语言模型 content: language modeling(语言模型知识) pre-trained langue models(PLMs)(预训练的模型整体的一个分类) fine-tuning approaches GPT and BERT(…...
Linux系统中编写bash脚本进行mysql的数据同步
一、为何要用脚本做数据同步 (一)、问题 我们的视频监控平台云服务器,需要向上级的服务器定期同步一些数据表的数据,前期做了个程序,可以实现同步。但是,现在数据库的结构改了,结果又需要该程序…...
光耦驱动继电器电路图大全
光耦驱动继电器电路图(一) 注: 1U1-1脚可接12V,也可接5V,1U1导通,1Q1导通,1Q1-30V,线圈两端电压为11.7V. 1U1-1脚不接或接地,1U1不通,1Q1截止,1…...
【AI量化分析】小明在量化中使用交叉验证原理深度分析解读
进行交叉验证好处 提高模型的泛化能力:通过将数据集分成多个部分并使用其中的一部分数据进行模型训练,然后使用另一部分数据对模型进行测试,可以确保模型在未见过的数据上表现良好。这样可以降低模型过拟合或欠拟合的风险,提高模…...
2024最新版Visual Studio Code安装使用指南
2024最新版Visual Studio Code安装使用指南 Installation and Usage Guide for the Latest Visual Studio Code in 2024 By JacksonML Visual Studio Code最新版1.85已经于2023年11月由其官网 https://code.visualstudio.com正式发布,这是微软公司2024年发行的的最…...
接口请求重试八种方法
请求三方接口需要加入重试机制 一、循环重试 在请求接口的代码块中加入循环,如果请求失败则继续请求,直到请求成功或达到最大重试次数。 int retryTimes 3; for(int i 0;i < retryTimes;i){try{//请求接口的代码break;}catch(Exception e){//处理…...
【Linux 基础】常用基础指令(上)
文章目录 一、 创建新用户并设置密码二、ls指令ls指令基本概念ls指令的简写操作 三、pwd指令四、cd指令五、touch指令六、rm指令七、mkdir指令八、rmdir 指令 一、 创建新用户并设置密码 ls /home —— 查看存在多少用户 whoami —— 查看当前用户名 adduser 用户名 —— 创建新…...
【RT-DETR有效改进】EfficientFormerV2移动设备优化的视觉网络(附对比试验效果图)
前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…...
《动手学深度学习(PyTorch版)》笔记4.4
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...
Linux/Academy
Enumeration nmap 首先扫描目标端口对外开放情况 nmap -p- 10.10.10.215 -T4 发现对外开放了22,80,33060三个端口,端口详细信息如下 结果显示80端口运行着http,且给出了域名academy.htb,现将ip与域名写到/et/hosts中,然后从ht…...
windows .vscode的json文件配置 CMake 构建项目 调试窗口中文设置等
一、CMake 和 mingw64的安装和环境配置 二、tasks.json和launch.json文件配置 tasks.json {"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell&q…...
uniapp canvas做的刮刮乐解决蒙层能自定义图片
最近给湖南中烟做元春活动,一个月要开发4个小活动,这个是其中一个难度一般,最难的是一个类似鲤鱼跃龙门的小游戏,哎,真实为难我这个“拍黄片”的。下面是主要代码。 <canvas :style"{width:widthpx,height:hei…...
利用SPI,结合数据库连接池durid进行数据服务架构灵活设计
接着上一篇文章业务开始围绕原始凭证展开,而展开的基础无疑是围绕着科目展开的。首先我们业务层面以财政部的小企业会计准则的一级科目引入软件中。下面我们来考虑如何将科目切入软件更加灵活,方便业务扩展、维护与升级。 SPI是首先想到的数据服务方式 为什么会想到它呢?首…...
自动驾驶的决策层逻辑
作者 / 阿宝 编辑 / 阿宝 出品 / 阿宝1990 自动驾驶意味着决策责任方的转移 我国2020至2025年将会是向高级自动驾驶跨越的关键5年。自动驾驶等级提高意味着对驾驶员参与度的需求降低,以L3级别为界,低级别自动驾驶环境监测主体和决策责任方仍保留于驾驶…...
排序算法——希尔排序算法详解
希尔排序算法详解 一. 引言1. 背景介绍1.1 数据排序的重要性1.2 希尔排序的由来 2. 排序算法的分类2.1 比较排序和非比较排序2.2 希尔排序的类型 二. 希尔排序基本概念1. 希尔排序的定义1.1 缩小增量排序1.2 插入排序的变种 2. 希尔排序的工作原理2.1 分组2.2 插入排序2.3 逐步…...
Docker 容器内运行 mysqldump 命令来导出 MySQL 数据库,自动化备份
备份容器数据库命令: docker exec 容器名称或ID mysqldump -u用户名 -p密码 数据库名称 > 导出文件.sql请替换以下占位符: 容器名称或ID:您的 MySQL 容器的名称或ID。用户名:您的 MySQL 用户名。密码:您的 MySQL …...
Windows 10/11打印服务总罢工?别急着重装,试试这几招修复Print Spooler自动停止
Windows 10/11打印服务罢工?5种专业修复方案拯救Print Spooler 办公室里最令人抓狂的时刻之一,就是当你急需打印文件时,发现打印机毫无反应。你检查服务管理器,发现那个关键的Print Spooler服务又自动停止了。这种情况在Windows …...
3分钟掌握FSearch:Linux系统文件搜索效率提升300%的终极方案
3分钟掌握FSearch:Linux系统文件搜索效率提升300%的终极方案 【免费下载链接】fsearch A fast file search utility for Unix-like systems based on GTK3 项目地址: https://gitcode.com/gh_mirrors/fs/fsearch 还在为Linux系统中寻找文件而烦恼吗ÿ…...
Visual C++运行库终极指南:如何一键修复所有Windows程序依赖问题
Visual C运行库终极指南:如何一键修复所有Windows程序依赖问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过打开软件时突然弹出&…...
SpeexDSP音频处理库深度解析:3种核心算法实现与40%性能优化实战
SpeexDSP音频处理库深度解析:3种核心算法实现与40%性能优化实战 【免费下载链接】speexdsp Speex audio processing library - THIS IS A MIRROR, DEVELOPMENT HAPPENS AT https://gitlab.xiph.org/xiph/speexdsp 项目地址: https://gitcode.com/gh_mirrors/sp/sp…...
5分钟掌握百度网盘高速下载神器:完全免费的开源解析工具终极指南
5分钟掌握百度网盘高速下载神器:完全免费的开源解析工具终极指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘非会员下载速度只有几十KB而烦恼吗…...
避坑指南:为什么你的PyTorch 1.8 + CUDA 10.1跑不了Grad-CAM?深入torch.fx模块依赖
避坑指南:为什么你的PyTorch 1.8 CUDA 10.1跑不了Grad-CAM?深入torch.fx模块依赖 当你兴致勃勃地准备用Grad-CAM可视化模型注意力时,终端突然抛出ModuleNotFoundError: No module named torch.fx——这个看似简单的报错背后,其实…...
告别日志硬编码:BizLog组件在SpringBoot中的实战应用指南
1. 为什么我们需要BizLog组件 记得去年接手一个电商项目时,遇到一个典型问题:产品经理要求在用户下单、修改订单、取消订单等关键操作时,都要记录详细的操作日志。刚开始我直接在业务代码里写日志记录逻辑,结果不到一个月就发现代…...
Windows下Carla编译启动卡在75%?别急着重装,先检查这个隐藏的压缩包
Windows下Carla编译启动卡在75%?别急着重装,先检查这个隐藏的压缩包 当你满怀期待地在Windows上完成Carla的编译,输入make launch命令后,进度条却在75%处戛然而止,弹出一个冰冷的"Fatal error"对话框——这…...
YOLOv8植物病害识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)
摘要 植物病害是威胁全球农业产量与质量的主要因素之一,传统的人工识别方法依赖专家经验,效率低、主观性强。本文基于YOLOv8目标检测算法,构建了一套涵盖30类植物及其叶片病害的检测系统,包括苹果、玉米、马铃薯、番茄、葡萄等主…...
Kubernetes二进制文件管理工具:自动化安装与多版本切换实践
1. 项目概述与核心价值在云原生和容器化技术成为主流的今天,Kubernetes 无疑是这个领域的基石。无论是开发、测试还是生产环境,我们都需要一套稳定、可靠的 Kubernetes 集群。然而,对于很多开发者、运维工程师,甚至是刚开始接触云…...
