设计模式是一种可以在开发中重复使用的解决方案,能够提高代码的可维护性、扩展性和复用性。C# 中常见的设计模式包括单例模式、工厂模式、观察者模式、策略模式等。本文将介绍这些常见的设计模式,并探讨 SOLID 原则和依赖注入(Dependency Injection)的重要性。
1. 常见设计模式
单例模式(Singleton)
单例模式 确保一个类只有一个实例,并提供全局访问点。它在需要共享资源或控制全局状态的情况下非常有用。
public class Singleton
{
private static Singleton instance;
private static readonly object lockObj = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
lock (lockObj)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
在上面的例子中,Singleton
类通过静态 Instance
属性保证全局唯一性,并使用双重锁定确保线程安全。
工厂模式(Factory)
工厂模式 提供了一种创建对象的接口,而不是直接实例化类。它将对象的创建与业务逻辑解耦。
public interface IProduct
{
void Create();
}
public class ConcreteProductA : IProduct
{
public void Create() => Console.WriteLine("Product A created");
}
public class ConcreteProductB : IProduct
{
public void Create() => Console.WriteLine("Product B created");
}
public class ProductFactory
{
public static IProduct GetProduct(string type)
{
return type switch
{
"A" => new ConcreteProductA(),
"B" => new ConcreteProductB(),
_ => throw new ArgumentException("Invalid product type")
};
}
}
在这个示例中,工厂方法 GetProduct
负责创建 ConcreteProductA
或 ConcreteProductB
,而客户端无需知道具体实现细节。
观察者模式(Observer)
观察者模式 定义了对象间的一对多依赖关系,当一个对象的状态改变时,依赖它的对象会收到通知并自动更新。这个模式常用于事件驱动的系统中。
public class Subject
{
private List<IObserver> observers = new List<IObserver>();
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();
}
}
}
public interface IObserver
{
void Update();
}
public class ConcreteObserver : IObserver
{
public void Update() => Console.WriteLine("Observer notified");
}
在这个示例中,Subject
维护了一个观察者列表,状态改变时,Notify
方法通知所有观察者。
策略模式(Strategy)
策略模式 允许在运行时选择算法或策略,避免在代码中使用大量的条件语句。每个策略都是一个独立的类,封装了具体的算法或行为。
public interface IStrategy
{
void Execute();
}
public class ConcreteStrategyA : IStrategy
{
public void Execute() => Console.WriteLine("Executing Strategy A");
}
public class ConcreteStrategyB : IStrategy
{
public void Execute() => Console.WriteLine("Executing Strategy B");
}
public class Context
{
private IStrategy strategy;
public Context(IStrategy strategy) => this.strategy = strategy;
public void ExecuteStrategy() => strategy.Execute();
}
在这个示例中,Context
类根据不同的策略执行相应的算法,策略可以在运行时动态选择。
2. SOLID 原则
SOLID 是面向对象设计的五大原则,旨在提高代码的可维护性和扩展性。这五个原则包括:
- S :单一职责原则(Single Responsibility Principle)
- 一个类应该只有一个职责。
- O :开闭原则(Open/Closed Principle)
- 软件实体应该对扩展开放,对修改关闭。
- L :里氏替换原则(Liskov Substitution Principle)
- 子类对象应该可以替换父类对象,并且不会导致错误。
- I :接口隔离原则(Interface Segregation Principle)
- 接口应该小而专,避免臃肿的接口。
- D :依赖倒置原则(Dependency Inversion Principle)
- 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
这些原则确保代码设计更加清晰、灵活,并且容易扩展。例如,遵循单一职责原则可以避免一个类承担太多职责,增加了代码的可维护性;而开闭原则确保我们可以在不修改现有代码的情况下进行功能扩展。
3. 依赖注入(Dependency Injection)
依赖注入 是实现 SOLID 原则(尤其是依赖倒置原则)的重要手段。它允许我们将类的依赖项通过外部注入,而不是让类自行实例化依赖项,从而提高代码的可测试性和灵活性。
构造函数注入
public interface IService
{
void Serve();
}
public class Service : IService
{
public void Serve() => Console.WriteLine("Service Called");
}
public class Client
{
private readonly IService service;
public Client(IService service)
{
this.service = service;
}
public void Start() => service.Serve();
}
在这个示例中,Client
类不直接依赖 Service
类,而是依赖于 IService
接口,通过构造函数将实现传递给 Client
,使得 Client
更加灵活。
使用依赖注入框架
在 C# 中,通常会使用依赖注入框架(如 ASP.NET Core 的内置 DI 容器)来自动管理依赖关系。
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IService, Service>();
services.AddTransient<Client>();
}
通过 DI 容器,可以自动解析依赖项并注入到构造函数中,无需手动实例化对象。这种方式极大简化了对象的管理,提升了可维护性和可测试性。
结论
设计模式和 SOLID 原则是提高代码质量、灵活性和可扩展性的有效工具。通过合理运用设计模式,我们可以解决常见的开发问题,简化系统的设计。SOLID 原则确保我们的代码结构更加清晰,避免复杂的耦合和难以维护的代码。
- 单例模式:控制类的实例数量,适用于全局唯一对象。
- 工厂模式:通过工厂类创建对象,解耦了对象的创建和使用。
- 观察者模式:使得对象间的变化可以被自动通知,适用于事件驱动的场景。
- 策略模式:允许动态选择行为或算法,避免条件判断过多的代码。
- SOLID 原则 提高了代码设计的健壮性。
- 依赖注入:通过外部注入依赖项,减少了类之间的耦合。
掌握这些设计模式和原则可以显著提升开发效率和代码质量。如果你有更多关于设计模式或依赖注入的疑问,欢迎继续探讨!
这篇博客为你介绍了常见的设计模式、SOLID 原则以及依赖注入的相关概念。如果你有任何问题或需要具体的实现示例,欢迎联系我!