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 …...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...