.NET 9时代革新:四大传统设计模式已成过去式!

作者:微信公众号:【架构师老卢】
4-6 8:38
3

框架进化论

伴随每个新版本.NET的发布,微软都在用内置功能重塑软件开发范式。.NET 9延续这一传统,通过强化依赖注入、事件处理、中间件和Entity Framework Core等核心模块,让诸多经典设计模式失去了用武之地。

本文将深度解析这些被.NET 9"淘汰"的设计模式,揭示其背后技术演进的底层逻辑:

  1. 单例模式 → 内置依赖注入
  2. 工厂模式 → 服务容器与依赖注入
  3. 观察者模式 → .NET事件系统与Reactive扩展
  4. 仓储模式 → EF Core 8直接实现

1. 单例模式 → 依赖注入容器

为何曾经需要单例模式?

作为经典设计模式之首,单例模式通过强制唯一实例解决全局资源管理问题。典型应用场景包括: • 缓存管理 • 日志记录 • 配置中心 • 数据库连接池

传统手动实现存在三大痛点:

public class SingletonService
{
    private static SingletonService? _instance;
    private static readonly object _lock = new object();

    private SingletonService() { }
    
    public static SingletonService Instance
    {
        get
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new SingletonService();
                }
                return _instance;
            }
        }
    }
    
    public void DoSomething()
    {
        Console.WriteLine("单例方法调用");
    }
}

致命缺陷分析: • 线程安全依赖显式锁机制 • 生命周期管理完全手动化 • 单元测试时难以重置状态

现代方案:依赖注入革命

.NET 9内置容器原生支持单例生命周期:

// 服务注册
builder.Services.AddSingleton<SingletonService>();

// 服务消费
public class MyComponent
{
    private readonly SingletonService _service;

    public MyComponent(SingletonService service)
    {
        _service = service;
    }
    
    public void Execute() => _service.DoSomething();
}

技术红利: • 容器自动保证线程安全 • 实现真正的按需延迟初始化 • 支持模拟对象进行单元测试


2. 工厂模式 → 依赖注入与服务定位

传统工厂模式的困境

工厂模式用于封装对象创建逻辑,但存在致命缺陷:

public interface ICar { void Drive(); }

public class BMW : ICar { public void Drive()=>Console.WriteLine("BMW驾驶体验"); }

public static class CarFactory
{
    public static ICar Create(string type) => 
        type switch { "BMW" => new BMW(), _ => throw new ArgumentException() };
}

违背开闭原则的代价: • 新增车型必须修改工厂类 • 工厂方法膨胀导致维护困难 • 依赖关系隐式耦合

依赖注入新范式

// 服务注册
builder.Services.AddTransient<ICar, BMW>();

// 服务消费
public class CarService
{
    private readonly ICar _car;

    public CarService(ICar car) => _car = car;

    public void Start() => _car.Drive();
}

架构优势: • 0代码侵入实现多态扩展 • 依赖关系显式声明 • 测试时可直接注入Mock对象


3. 观察者模式 → 事件系统与响应式编程

传统观察者实现

public interface IObserver { void Update(string message); }

public class Publisher
{
    private List<IObserver> _observers = new();
    
    public void Subscribe(IObserver observer) => _observers.Add(observer);
    
    public void NotifyAll(string msg) => 
        _observers.ForEach(o => o.Update(msg));
}

隐藏的技术债务: • 手动维护订阅者列表 • 内存泄漏风险(未正确取消订阅) • 通知顺序无法控制

.NET原生解决方案

public class EventPublisher
{
    // 定义强类型事件
    public event EventHandler<string>? OnDataChanged;
    
    public void PublishChange(string data) =>
        OnDataChanged?.Invoke(this, data);
}

public class Subscriber
{
    public Subscriber(EventPublisher publisher) =>
        publisher.OnDataChanged += (s, e) => 
            Console.WriteLine($"收到更新:{e}");
}

关键技术突破: • 编译时类型安全保障 • 自动内存管理(+=/-=语法) • 支持异步事件处理


4. 仓储模式 → EF Core 8直接实现

仓储模式的兴衰史

传统仓储层设计:

public interface IUserRepo
{
    Task<User> GetByIdAsync(int id);
    Task AddAsync(User user);
}

public class UserRepo : IUserRepo
{
    private readonly AppDbContext _context;
    
    public UserRepo(AppDbContext context) => _context = context;
    
    public async Task<User> GetByIdAsync(int id) =>
        await _context.Users.FindAsync(id);
}

过度抽象的代价: • 增加无谓的抽象层次 • 需要额外维护接口与实现 • 抵消了EF Core的优势特性

EF Core 8实战

public class UserService
{
    private readonly AppDbContext _context;

    public UserService(AppDbContext context) => _context = context;

    public async Task<List<User>> GetAll() => 
        await _context.Users.ToListAsync();

    public async Task Add(User user) =>
        await _context.Users.AddAsync(user);
}

性能飞跃的关键: • 直接利用DbContext的变更追踪 • 内置延迟加载与批处理 • 减少一次内存分配层级

单元测试新范式

var options = new DbContextOptionsBuilder<AppDbContext>()
    .UseInMemoryDatabase(databaseName: "TestDb")
    .Options;

using var context = new AppDbContext(options);
var service = new UserService(context);

// 直接操作内存数据库完成测试
await service.Add(new User());
var count = await service.GetAll().CountAsync();

拥抱框架进化论

.NET 9的发展轨迹清晰展现一个趋势:框架能力边界不断拓展,迫使开发者从重复造轮子转向业务价值创造。当您还在纠结如何实现线程安全的单例时,框架早已提供经过充分优化的解决方案;当您试图编写通用仓储接口时,EF Core 8已经将数据访问简化到极致。

这些技术演进不是要否定设计模式的经典价值,而是提醒我们:优秀架构师应该像园丁修剪枝杈那样,去除冗余设计,让框架的能力自然流淌在代码之中。在.NET 9时代,明智的选择是深入理解框架特性,而非固守过时的设计模式教条。

相关留言评论
昵称:
邮箱:
阅读排行