靳谷雪
2026-2-9 20:35:12
观察者模式(Observer Pattern)是一种软件设计模式,属于对象行为模式的一种。它定义了一种一对多的依赖关系,使得多个观察者对象可以同时监听某个主题对象(也称被观察者)。当主题对象的状态发生改变时,会自动通知所有注册的观察者,让它们能够自动更新自身状态。
这种模式的核心在于解耦:主题对象无需知道具体有哪些观察者,只需维护一个观察者列表并在状态变化时通知它们;而观察者也只需关注自己感兴趣的事件,无需主动轮询主题状态。
观察者模式在软件架构中被广泛应用,尤其适用于事件处理系统、用户界面与业务数据的同步、权限管理等场景。例如,在图形界面中,界面元素(观察者)可以监听后台数据模型(主题)的变化,一旦数据更新,界面自动刷新。
主要角色
- 主题(Subject):也称为被观察者,它是一个具体的对象,通过attach()方法注册观察者,通过notifyObservers()方法通知观察者。
- 观察者(Observer):也称为观察者,它定义了一个更新接口,当主题状态改变时,得到通知并进行相应的处理。
- 具体主题(ConcreteSubject):是主题的具体实现对象,它保存着观察者对象的列表,并实现了抽象主题中的方法。
- 具体观察者(ConcreteObserver):是观察者的具体实现对象,它存储着具体主题的引用,实现了抽象观察者中的更新接口。
推模式与拉模式
在通知机制上,观察者模式通常分为两种实现方式:
- 推模式(Push):主题对象将状态数据主动推送给观察者,观察者无需额外获取。
- 拉模式(Pull):主题仅发送通知,观察者主动拉取所需数据,通常通过主题对象的引用获取最新状态。
观察者模式也常被称为发布-订阅模式(Publish/Subscribe)、模型-视图模式(Model/View)或源-监听器模式(Source/Listener)。
应用场景
观察者模式通常用于以下场景:
- 事件处理:观察者模式可以用于事件处理系统,在系统中,事件源对象可以将事件通知所有的观察者对象,以便观察者对象可以执行相应的操作。
- 状态监控:观察者模式可以用于监控对象的状态变化,在状态改变时,通知所有观察者对象。
- MVC模式:MVC模式中,视图与数据模型是分离的,视图通常是数据模型的观察者。当数据模型发生变化时,通知所有的视图对象,更新视图。
- 消息系统:观察者模式可以用于实现消息系统,在系统中,消息发布者可以将消息通知所有的观察者对象,以便观察者对象可以执行相应的操作。
- GUI开发:观察者模式可以用于GUI开发,在GUI中,图形对象可以作为观察者,与数据模型对象建立关联,当数据模型发生变化时,通知所有的观察者对象,更新界面。
优缺点
观察者模式是一种行为型设计模式,定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新状态。
优点包括:
- 松耦合:观察者模式实现了对象之间的松耦合,被观察者和观察者之间的关系被解耦,它们都可以独立地变化。
- 对象的状态更新:观察者模式实现了对象的状态更新,当对象的状态发生变化时,所有依赖它的对象都会收到通知并自动更新状态。
- 拓展性:在观察者模式中,可以很方便地增加或删除观察者,实现拓展性。
缺点包括:
- 观察者模式可能导致事件的洪泛,即被观察者的状态变化导致大量的信息传递和处理,这可能降低程序的性能。
- 可能存在循环依赖问题:当观察者和被观察者之间存在互相依赖时,就会出现循环依赖的问题,这会导致系统的稳定性降低。
- 观察者模式需要考虑开发效率和运行效率两个方面,开发效率较高,但需要考虑如何优化运行效率。
模式实现
委托方式实现
- using System; // 定义委托 public delegate void NotifyEventHandler(string message); // 主题类 public class Subject { public event NotifyEventHandler NotifyEvent; // 声明事件 public void ChangeState() { Console.WriteLine("Subject: 我的状态改变了!"); NotifyEvent?.Invoke("状态已改变"); // 触发事件 } } // 观察者类 public class Observer { public void OnNotify(string message) { Console.WriteLine($"Observer: 收到通知 - {message}"); } } // 使用示例 class Program { static void Main() { Subject subject = new Subject(); Observer observer = new Observer(); // 订阅事件 subject.NotifyEvent += observer.OnNotify; // 触发状态改变 subject.ChangeState(); // 取消订阅 subject.NotifyEvent -= observer.OnNotify; } }
复制代码 接口方式实现
- using System; using System.Collections.Generic; // 观察者接口 public interface IObserver { void Update(string message); } // 主题接口 public interface ISubject { void Attach(IObserver observer); void Detach(IObserver observer); void Notify(string message); } // 具体主题类 public class NewsSubject : ISubject { private readonly List _observers = new List(); public void Attach(IObserver observer) { _observers.Add(observer); } public void Detach(IObserver observer) { _observers.Remove(observer); } public void Notify(string message) { foreach (var observer in _observers) { observer.Update(message); } } } // 具体观察者类 public class UserObserver : IObserver { private readonly string _userName; public UserObserver(string name) { _userName = name; } public void Update(string message) { Console.WriteLine($"{_userName} 收到消息: {message}"); } } // 测试类 public class Program { public static void Main() { // 创建主题 ISubject news = new NewsSubject(); // 创建观察者 IObserver user1 = new UserObserver("张三"); IObserver user2 = new UserObserver("李四"); // 注册观察者 news.Attach(user1); news.Attach(user2); // 通知观察者 news.Notify("最新新闻:C#观察者模式实现成功!"); // 移除一个观察者 news.Detach(user1); // 再次通知 news.Notify("更新新闻:张三已退订。"); } }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|
|
|
|
|
相关推荐
|
|
|