C# 设计模式:观察者模式深度解析与事件实现

Leo
Leo
发布时间:2026-10-13 | 5人浏览过
原创

观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在 C# 开发中,除了标准的类实现外,利用内置的委托与事件机制可以更优雅地实现这一模式,有效降低模块间的耦合度。

目标与核心概念

观察者模式(Observer Pattern),有时也称为发布/订阅模式,旨在解决系统对象间紧密耦合带来的维护难题。其核心逻辑是:Subject(主题)维护一个观察者列表,当自身状态变更时,主动通知列表中所有 Observer(观察者)执行更新。这种机制允许独立改变主题和观察者,而无需修改对方代码。

准备条件

  • 了解 C# 面向对象基本概念(类、接口、继承)。
  • 理解委托(Delegate)与事件(Event)的基础语法。
  • 具备基本的控制台应用程序开发环境。

真实操作顺序

第1步:标准观察者模式实现

目的:通过明确的类层次结构(抽象主题、具体主题、抽象观察者、具体观察者)建立基础的通知机制。

操作:

  1. 定义角色接口:创建 Subject 抽象基类,包含 Attach、Dettach 和 Notify 方法,用于管理观察者集合。同时定义 Observer 抽象基类,声明 Update 虚方法。
  2. 实现具体主题:创建 ConcreteSubject,继承自 Subject,存储状态并在 Notify 时遍历调用观察者的 Update。
  3. 实现具体观察者:创建 ConcreteObserver,保存对主题的引用,在 Update 中同步主题状态。

基础代码结构

/// <summary>
/// 抽象主题类
/// </summary>
public abstract class Subject
{
 private IList<Observer> observers = new List<Observer>();

 public void Attach(Observer observer)
 {
  observers.Add(observer);
 }

 public void Dettach(Observer observer)
 {
  observers.Remove(observer);
 }

 public void Notify()
 {
  foreach (Observer o in observers)
  {
  o.Update();
  }
 }
}

/// <summary>
/// 抽象观察者类
/// </summary>
public abstract class Observer
{
 public abstract void Update();
}

/// <summary>
/// 具体观察者
/// </summary>
public class ConcreteObserver : Observer
{
 private string name;
 private ConcreteSubject subject;

 public ConcreteSubject Subject
 {
  get { return subject; }
  set { subject = value; }
 }

 public ConcreteObserver(ConcreteSubject subject, string name)
 {
  this.subject = subject;
  this.name = name;
 }

 public override void Update()
 {
  Console.WriteLine("The observer's state of {0} is {1}", name, subject.SubjectState);
 }
}

第2步:业务场景应用——订单处理

目的:在实际业务中演示如何动态注册多个观察者(会计、出纳、配送员)并触发联动。

操作:

  1. 设定主题:以“客户”为 Subject,当其状态变为“已付款”时触发通知。
  2. 设定观察者:会计、出纳、配送员分别继承抽象观察者 JobStation,实现各自的 Update 逻辑。
  3. 客户端集成:实例化客户对象,依次添加各岗位人员作为观察者,更改客户状态后调用 Notify。

场景代码实现

// 抽象主题
public interface ISubject
{
 void Notify();
}

// 工作岗位(抽象观察者)
public abstract class JobStation
{
 public abstract void Update();
}

// 客户(具体主题)
public class Customer : ISubject
{
 private string customerState;
 private IList<JobStation> observers = new List<JobStation>();

 public void Attach(JobStation observer) { observers.Add(observer); }
 public void Dettach(JobStation observer) { observers.Remove(observer); }
 public string CustomerState
 {
  get { return customerState; }
  set { customerState = value; }
 }
 public void Notify()
 {
  foreach (JobStation o in observers) o.Update();
 }
}

// 具体观察者:会计
public class Accountant : JobStation
{
 private Customer customer;
 public Accountant(Customer customer) { this.customer = customer; }
 public override void Update()
 {
  if (customer.CustomerState == "已付款")
   Console.WriteLine("我是会计,我来开具发票。");
 }
}

// 类似地实现 Cashier 和 Deliveryman...

第3步:进阶优化——使用 C# 事件与委托

目的:利用语言特性完全消除代码层面的耦合,使观察者不再需要引用主题类。

原理:委托是对方法的封装,事件是基于委托的发布/订阅机制。订阅使用 +=,取消订阅使用 -=。

操作:

  1. 声明委托:定义 CustomerEventHandler,规定通知回调的方法签名。
  2. 暴露事件:在 Customer 类中声明 event CustomerEventHandler Update。
  3. 解耦观察者:移除观察者类中对 Customer 的引用,改为直接绑定主题类的 Notify 方法或特定动作。

事件版代码实现

// 声明委托
public delegate void CustomerEventHandler();

// 具体主题(仅负责触发)
public class Customer
{
 public event CustomerEventHandler Update;
 
 public void Notify()
 {
  if (Update != null) Update();
 }
}

// 观察者类(完全独立)
public class Accountant
{
 public void GiveInvoice() { Console.WriteLine("我是会计,我来开具发票。"); }
}

// 客户端注册
static void Main(string[] args)
{
 var customer = new Customer();
 var accountant = new Accountant();
 var cashier = new Cashier();
 var deliveryman = new Deliveryman();

 // 订阅事件
 customer.Update += accountant.GiveInvoice;
 customer.Update += cashier.Recoded;
 customer.Update += deliveryman.Dilliver;

 customer.Notify(); // 触发通知
}

第4步:结果验证与对比

运行上述代码,控制台将按顺序输出会计、出纳和配送员的响应信息。这表明主题状态变更成功触发了所有注册的观察者行为。

完成判断

  • 功能验证:修改 CustomerState 后,所有相关观察者均执行了 Update 或其对应的处理方法。
  • 解耦程度:在事件版本中,Accountant 等类不再继承自任何抽象基类,也不持有 Customer 实例引用,仅通过委托链进行通信,符合“开闭原则”和“依赖倒置原则”。

简要总结

观察者模式是构建松散耦合系统的基石。在传统面向对象设计中,它通过继承和多态实现;而在 C# 等现代语言中,结合 delegate 和 event 可以进一步简化架构,避免复杂的类图依赖。建议在数据模型变化需通知 UI、日志记录或第三方服务回调等场景中优先考虑此模式。

以上就是C# 观察者模式详细内容的资料,更多关于C# 设计模式及事件委托的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表