引言
设计模式是软件开发中经过验证的、可复用的解决方案,用于解决特定上下文中反复出现的问题。在.NET生态系统中,许多框架都采用了各种设计模式来提高代码的可维护性、可扩展性和可测试性。本文将详细探讨ASP.NET Core、Entity Framework和WPF这三个主流框架中常见的设计模式应用,帮助开发者更好地理解和应用这些模式。
文章目录
引言ASP.NET Core中的设计模式1. 依赖注入(Dependency Injection)模式2. 中介者(Mediator)模式3. 管道(Pipeline)模式4. 选项(Options)模式
Entity Framework Core中的设计模式1. 仓储(Repository)与工作单元(Unit of Work)模式2. 规约(Specification)模式3. 领域驱动设计(DDD)模式
WPF中的设计模式1. MVVM(Model-View-ViewModel)模式2. 命令(Command)模式3. 观察者(Observer)模式4. 装饰器(Decorator)模式
总结与实践建议参考资料
ASP.NET Core中的设计模式
ASP.NET Core是一个跨平台、高性能的开源框架,用于构建现代化的云端应用。其架构中融入了多种设计模式,使开发人员能够构建灵活且可维护的应用程序。
1. 依赖注入(Dependency Injection)模式
依赖注入是ASP.NET Core的核心特性,框架本身就内置了DI容器。
// 在Startup.cs或Program.cs中注册服务
public void ConfigureServices(IServiceCollection services)
{
// 注册服务的生命周期
services.AddTransient
services.AddScoped
services.AddSingleton
}
// 在控制器中通过构造函数注入
public class HomeController : Controller
{
private readonly ITransientService _transientService;
// 依赖通过构造函数注入
public HomeController(ITransientService transientService)
{
_transientService = transientService; // 控制器不需要知道具体实现
}
}
优势:
降低组件间的耦合度提高代码的可测试性简化配置管理提高代码的可维护性和可扩展性
2. 中介者(Mediator)模式
ASP.NET Core中常见的MediatR库实现了中介者模式,用于处理请求/响应和事件通知。
// 定义请求和处理程序
public class GetCustomerQuery : IRequest
{
public int CustomerId { get; set; }
}
public class GetCustomerQueryHandler : IRequestHandler
{
private readonly ICustomerRepository _repository;
public GetCustomerQueryHandler(ICustomerRepository repository)
{
_repository = repository;
}
public async Task
{
// 处理查询逻辑
var customer = await _repository.GetByIdAsync(request.CustomerId);
return new CustomerDto { Id = customer.Id, Name = customer.Name };
}
}
// 在控制器中使用
public class CustomerController : Controller
{
private readonly IMediator _mediator;
public CustomerController(IMediator mediator)
{
_mediator = mediator;
}
public async Task
{
// 发送请求到中介者,由中介者找到合适的处理程序
var customer = await _mediator.Send(new GetCustomerQuery { CustomerId = id });
return View(customer);
}
}
优势:
解耦请求的发送者和接收者简化复杂的业务逻辑支持横切关注点(如日志记录、缓存等)
3. 管道(Pipeline)模式
ASP.NET Core中间件是典型的管道模式应用,请求通过一系列组件顺序处理。
public void Configure(IApplicationBuilder app)
{
// 管道中的每个中间件按顺序处理请求
app.UseExceptionHandler("/Error");
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
优势:
可以灵活地添加或移除处理步骤每个中间件只关注特定职责提高代码的可维护性和可测试性
4. 选项(Options)模式
ASP.NET Core使用选项模式来配置服务行为。
// 定义选项类
public class EmailSettings
{
public string SmtpServer { get; set; }
public int Port { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
// 注册选项
public void ConfigureServices(IServiceCollection services)
{
services.Configure
}
// 在服务中使用选项
public class EmailService
{
private readonly EmailSettings _settings;
public EmailService(IOptions
{
_settings = options.Value;
}
public void SendEmail(string to, string subject, string body)
{
// 使用_settings中的配置
}
}
优势:
集中管理配置强类型配置访问支持运行时更新配置
Entity Framework Core中的设计模式
Entity Framework Core是.NET的现代化ORM框架,它也采用了多种设计模式来简化数据访问层的开发。
1. 仓储(Repository)与工作单元(Unit of Work)模式
仓储模式封装数据访问逻辑,工作单元模式管理事务一致性。
// 仓储接口
public interface ICustomerRepository
{
Task
Task
Task AddAsync(Customer customer);
Task UpdateAsync(Customer customer);
Task DeleteAsync(int id);
}
// 工作单元接口
public interface IUnitOfWork
{
ICustomerRepository Customers { get; }
IOrderRepository Orders { get; }
Task
}
// EF Core实现
public class CustomerRepository : ICustomerRepository
{
private readonly AppDbContext _context;
public CustomerRepository(AppDbContext context)
{
_context = context;
}
public async Task
{
return await _context.Customers.FindAsync(id);
}
// 实现其他方法...
}
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
private ICustomerRepository _customerRepository;
private IOrderRepository _orderRepository;
public UnitOfWork(AppDbContext context)
{
_context = context;
}
public ICustomerRepository Customers =>
_customerRepository ??= new CustomerRepository(_context);
public IOrderRepository Orders =>
_orderRepository ??= new OrderRepository(_context);
public async Task
{
return await _context.SaveChangesAsync();
}
}
优势:
隔离数据访问逻辑,提高可测试性确保事务一致性提供统一的数据访问API
2. 规约(Specification)模式
规约模式用于封装查询条件,使它们可重用和可组合。
// 基础规约接口
public interface ISpecification
{
Expression
List
List
Expression
Expression
}
// 基础规约实现
public abstract class BaseSpecification
{
public Expression
public List
public List
public Expression
public Expression
protected BaseSpecification(Expression
{
Criteria = criteria;
}
protected void AddInclude(Expression
{
Includes.Add(includeExpression);
}
protected void AddInclude(string includeString)
{
IncludeStrings.Add(includeString);
}
protected void ApplyOrderBy(Expression
{
OrderBy = orderByExpression;
}
protected void ApplyOrderByDescending(Expression
{
OrderByDescending = orderByDescendingExpression;
}
}
// 具体规约实现
public class CustomerWithOrdersSpecification : BaseSpecification
{
public CustomerWithOrdersSpecification(int customerId)
: base(c => c.Id == customerId)
{
AddInclude(c => c.Orders);
}
}
// 在仓储中使用规约
public interface IRepository
{
Task
Task
Task
Task
}
public class Repository
{
protected readonly DbContext _dbContext;
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
public async Task
{
return await ApplySpecification(spec).ToListAsync();
}
private IQueryable
{
var query = _dbContext.Set
if (spec.Criteria != null)
query = query.Where(spec.Criteria);
query = spec.Includes.Aggregate(query, (current, include) => current.Include(include));
query = spec.IncludeStrings.Aggregate(query, (current, include) => current.Include(include));
if (spec.OrderBy != null)
query = query.OrderBy(spec.OrderBy);
else if (spec.OrderByDescending != null)
query = query.OrderByDescending(spec.OrderByDescending);
return query;
}
// 实现其他方法...
}
优势:
使查询条件可复用和组合提高代码可读性和可维护性支持复杂查询的构建
3. 领域驱动设计(DDD)模式
Entity Framework Core可以与DDD模式一起使用,构建富领域模型。
// 实体基类
public abstract class Entity
{
public int Id { get; protected set; }
protected Entity() { }
public override bool Equals(object obj)
{
var entity = obj as Entity;
if (entity == null) return false;
return Id == entity.Id;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
// 值对象
public class Address : ValueObject
{
public string Street { get; private set; }
public string City { get; private set; }
public string State { get; private set; }
public string Country { get; private set; }
public string ZipCode { get; private set; }
private Address() { } // EF Core需要
public Address(string street, string city, string state, string country, string zipCode)
{
Street = street;
City = city;
State = state;
Country = country;
ZipCode = zipCode;
}
protected override IEnumerable
{
yield return Street;
yield return City;
yield return State;
yield return Country;
yield return ZipCode;
}
}
// 聚合根
public class Order : Entity, IAggregateRoot
{
private readonly List
public IReadOnlyCollection
public decimal TotalAmount => _orderItems.Sum(i => i.UnitPrice * i.Quantity);
public OrderStatus Status { get; private set; }
public CustomerId CustomerId { get; private set; }
public Address ShippingAddress { get; private set; }
private Order() { } // EF Core需要
public Order(CustomerId customerId, Address shippingAddress)
{
CustomerId = customerId;
ShippingAddress = shippingAddress;
Status = OrderStatus.Created;
}
public void AddOrderItem(ProductId productId, decimal unitPrice, int quantity)
{
// 领域逻辑:检查产品是否已存在
var existingItem = _orderItems.SingleOrDefault(i => i.ProductId == productId);
if (existingItem != null)
{
// 更新现有项目数量
existingItem.UpdateQuantity(existingItem.Quantity + quantity);
}
else
{
// 添加新项目
_orderItems.Add(new OrderItem(productId, unitPrice, quantity));
}
}
public void Confirm()
{
// 领域逻辑:确认订单
if (Status != OrderStatus.Created)
throw new OrderDomainException("只能确认处于'已创建'状态的订单");
Status = OrderStatus.Confirmed;
}
}
// DbContext配置
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions
public DbSet
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 配置值对象为拥有的实体
modelBuilder.Entity
.OwnsOne(o => o.ShippingAddress);
// 配置一对多关系
modelBuilder.Entity
.HasMany(o => o.OrderItems)
.WithOne()
.IsRequired();
// 其他配置...
}
}
优势:
将业务规则封装在领域模型中使用强类型的值对象增强类型安全支持聚合边界以确保数据一致性
WPF中的设计模式
Windows Presentation Foundation (WPF)是用于创建桌面应用的UI框架,它也充分利用了各种设计模式。
1. MVVM(Model-View-ViewModel)模式
MVVM是WPF应用程序中最常用的架构模式,它将应用程序分为三层:Model(模型)、View(视图)和ViewModel(视图模型)。
// Model - 表示数据和业务逻辑
public class Customer : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
// INotifyPropertyChanged实现
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// ViewModel - 适配Model供View使用,并提供命令
public class CustomerViewModel : INotifyPropertyChanged
{
private Customer _customer;
public CustomerViewModel(Customer customer)
{
_customer = customer;
SaveCommand = new RelayCommand(Save, CanSave);
}
public string Name
{
get => _customer.Name;
set
{
if (_customer.Name != value)
{
_customer.Name = value;
OnPropertyChanged(nameof(Name));
}
}
}
public ICommand SaveCommand { get; }
private bool CanSave()
{
return !string.IsNullOrWhiteSpace(Name);
}
private void Save()
{
// 保存客户数据
}
// INotifyPropertyChanged实现
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// View - XAML界面
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Customer" Height="300" Width="400">
优势:
实现关注点分离,提高代码的可维护性支持UI和业务逻辑的单元测试利用数据绑定简化UI更新逻辑
2. 命令(Command)模式
WPF支持命令模式,通过实现ICommand接口将用户操作与业务逻辑分离。
// 命令基类
public class RelayCommand : ICommand
{
private readonly Action
private readonly Predicate
public RelayCommand(Action
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
// 在ViewModel中使用命令
public class MainViewModel
{
public ICommand OpenCommand { get; }
public ICommand SaveCommand { get; }
public ICommand CloseCommand { get; }
public MainViewModel()
{
OpenCommand = new RelayCommand(Open);
SaveCommand = new RelayCommand(Save, CanSave);
CloseCommand = new RelayCommand(Close);
}
private void Open(object parameter)
{
// 打开文件逻辑
}
private void Save(object parameter)
{
// 保存文件逻辑
}
private bool CanSave(object parameter)
{
// 判断是否可以保存
return true;
}
private void Close(object parameter)
{
// 关闭操作逻辑
}
}
// 在XAML中使用命令
优势:
解耦UI事件和业务逻辑提高代码的可测试性支持命令的启用/禁用状态管理
3. 观察者(Observer)模式
WPF使用INotifyPropertyChanged和INotifyCollectionChanged接口实现观察者模式,使UI能够响应数据变化。
// ViewModel实现INotifyPropertyChanged
public class ProductViewModel : INotifyPropertyChanged
{
private decimal _price;
private int _quantity;
public decimal Price
{
get => _price;
set
{
if (_price != value)
{
_price = value;
OnPropertyChanged(nameof(Price));
OnPropertyChanged(nameof(Total)); // 相关属性也需要通知
}
}
}
public int Quantity
{
get => _quantity;
set
{
if (_quantity != value)
{
_quantity = value;
OnPropertyChanged(nameof(Quantity));
OnPropertyChanged(nameof(Total)); // 相关属性也需要通知
}
}
}
public decimal Total => Price * Quantity;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// 使用ObservableCollection实现集合变更通知
public class ProductsViewModel
{
public ObservableCollection
public ProductsViewModel()
{
Products = new ObservableCollection
// 添加产品
Products.Add(new ProductViewModel { Price = 10.99m, Quantity = 1 });
Products.Add(new ProductViewModel { Price = 25.49m, Quantity = 2 });
}
public void AddProduct(ProductViewModel product)
{
Products.Add(product); // 自动通知UI更新
}
public void RemoveProduct(ProductViewModel product)
{
Products.Remove(product); // 自动通知UI更新
}
}
// XAML数据绑定
优势:
自动更新UI,响应数据变化简化视图与数据模型的协调提供清晰的变更通知机制
4. 装饰器(Decorator)模式
WPF中的附加属性可以被视为装饰器模式的一种实现,它允许为现有元素添加新功能。
// 附加属性定义
public static class ValidationBehavior
{
public static readonly DependencyProperty IsRequiredProperty =
DependencyProperty.RegisterAttached(
"IsRequired",
typeof(bool),
typeof(ValidationBehavior),
new PropertyMetadata(false, OnIsRequiredChanged));
public static bool GetIsRequired(DependencyObject obj)
{
return (bool)obj.GetValue(IsRequiredProperty);
}
public static void SetIsRequired(DependencyObject obj, bool value)
{
obj.SetValue(IsRequiredProperty, value);
}
private static void OnIsRequiredChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox textBox)
{
if ((bool)e.NewValue)
{
textBox.TextChanged += TextBox_TextChanged;
// 初始验证
ValidateTextBox(textBox);
}
else
{
textBox.TextChanged -= TextBox_TextChanged;
// 移除验证样式
textBox.ClearValue(TextBox.BorderBrushProperty);
textBox.ToolTip = null;
}
}
}
private static void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
ValidateTextBox(sender as TextBox);
}
private static void ValidateTextBox(TextBox textBox)
{
if (string.IsNullOrWhiteSpace(textBox.Text))
{
// 显示错误
textBox.BorderBrush = Brushes.Red;
textBox.ToolTip = "该字段为必填项";
}
else
{
// 清除错误
textBox.ClearValue(TextBox.BorderBrushProperty);
textBox.ToolTip = null;
}
}
}
// 在XAML中使用附加属性
优势:
在不修改原有类的情况下扩展其功能增强代码的可复用性实现横切关注点分离
总结与实践建议
通过深入了解ASP.NET Core、Entity Framework Core和WPF中的常见设计模式应用,我们可以看到这些模式如何帮助开发者构建更加健壮、可维护和可扩展的应用程序。以下是应用这些设计模式时的一些实践建议:
不要过度设计:设计模式是工具,不是目标。根据项目的实际需求和复杂度选择适当的模式。
保持一致性:在一个项目中,尽量保持模式使用的一致性,避免混合使用多种风格的模式。
理解框架的内置模式:现代框架如ASP.NET Core已经内置了许多设计模式,理解它们可以避免"重新发明轮子"。
关注点分离:无论使用哪种模式,都应该确保关注点分离,使代码更易于维护和测试。
保持简单:选择最简单、最能满足需求的模式。复杂的模式可能导致更高的维护成本。
通过合理运用这些设计模式,我们可以构建更加健壮、灵活和可维护的.NET应用程序,从而提高开发效率和代码质量。
参考资料
ASP.NET Core 官方文档Entity Framework Core 官方文档WPF 官方文档.NET 架构指南设计模式:可复用面向对象软件的基础