文章目录
前言
在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 music
musicPlayer = new Mp4ToMp3Adapter(new Mp4MusicPlayer());
musicPlayer.Play("mp3"); // 输出:Playing MP4 music(通过适配器转换)
总结
通过使用这些常见的设计模式,我们可以更好地组织和管理代码,提高代码的可读性、可维护性和可扩展性。每个设计模式都有其独特的应用场景和优势,在实际项目中灵活运用可以有效解决各种问题。希望本文能够帮助读者理解C#设计模式的多样性,并在实践中加以应用。