前言

在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#设计模式的多样性,并在实践中加以应用。

更多推荐