C# 设计模式:观察者模式深度解析与事件实现
观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在 C# 开发中,除了标准的类实现外,利用内置的委托与事件机制可以更优雅地实现这一模式,有效降低模块间的耦合度。
目标与核心概念
观察者模式(Observer Pattern),有时也称为发布/订阅模式,旨在解决系统对象间紧密耦合带来的维护难题。其核心逻辑是:Subject(主题)维护一个观察者列表,当自身状态变更时,主动通知列表中所有 Observer(观察者)执行更新。这种机制允许独立改变主题和观察者,而无需修改对方代码。
准备条件
- 了解 C# 面向对象基本概念(类、接口、继承)。
- 理解委托(Delegate)与事件(Event)的基础语法。
- 具备基本的控制台应用程序开发环境。
真实操作顺序
第1步:标准观察者模式实现
目的:通过明确的类层次结构(抽象主题、具体主题、抽象观察者、具体观察者)建立基础的通知机制。
操作:
- 定义角色接口:创建
Subject抽象基类,包含Attach、Dettach和Notify方法,用于管理观察者集合。同时定义Observer抽象基类,声明Update虚方法。 - 实现具体主题:创建
ConcreteSubject,继承自Subject,存储状态并在Notify时遍历调用观察者的Update。 - 实现具体观察者:创建
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步:业务场景应用——订单处理
目的:在实际业务中演示如何动态注册多个观察者(会计、出纳、配送员)并触发联动。
操作:
- 设定主题:以“客户”为
Subject,当其状态变为“已付款”时触发通知。 - 设定观察者:会计、出纳、配送员分别继承抽象观察者
JobStation,实现各自的Update逻辑。 - 客户端集成:实例化客户对象,依次添加各岗位人员作为观察者,更改客户状态后调用
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# 事件与委托
目的:利用语言特性完全消除代码层面的耦合,使观察者不再需要引用主题类。
原理:委托是对方法的封装,事件是基于委托的发布/订阅机制。订阅使用 +=,取消订阅使用 -=。
操作:
- 声明委托:定义
CustomerEventHandler,规定通知回调的方法签名。 - 暴露事件:在
Customer类中声明event CustomerEventHandler Update。 - 解耦观察者:移除观察者类中对
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# 设计模式及事件委托的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













