观察者模式 (Observer Pattern)
观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常用于实现事件处理系统。
关键角色:
- Subject(主题) 也称为被观察者,它维护着一个观察者列表,并提供注册、取消注册以及通知观察者的方法。
- Observer(观察者) 是具体观察者的接口,定义了一个
Update
方法来接收主题状态改变的通知。
以下是为了解释概念而使用接口解释具体机制的代码,实际不会使用这种实现方式,除非你用的是JAVA之类的比较原始的语言。它需要使用接口来定义主题和观察者的行为,适用于需要高度抽象和接口严格分离的情况,代码较为繁琐,但易于扩展。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public interface ISubject { void RegisterObserver(IObserver observer); void RemoveObserver(IObserver observer); void NotifyObservers(); }
public interface IObserver { void Update(string message); }
public class WeatherData : ISubject { private List<IObserver> observers = new List<IObserver>(); private string currentWeather; public void RegisterObserver(IObserver observer) { observers.Add(observer); } public void RemoveObserver(IObserver observer) { observers.Remove(observer); } public void NotifyObservers() { foreach (var observer in observers) { observer.Update(currentWeather); } } public void SetWeather(string weather) { this.currentWeather = weather; NotifyObservers(); } }
public class CurrentConditionsDisplay : IObserver { public void Update(string message) { Console.WriteLine($"Current conditions display: {message}"); } }
|
C#里这么写就太麻烦了,而且高度抽象需要的接口太多,我们有 delegate
和 event
可用
使用 event 实现观察者模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public delegate void WeatherChangedEventHandler(string message);
public class WeatherData { public event WeatherChangedEventHandler WeatherChanged; private string currentWeather; public void SetWeather(string weather) { this.currentWeather = weather; OnWeatherChanged(weather); } protected virtual void OnWeatherChanged(string message) { WeatherChanged?.Invoke(message); } }
public class CurrentConditionsDisplay { public CurrentConditionsDisplay(WeatherData weatherData) { weatherData.WeatherChanged += DisplayUpdate; } private void DisplayUpdate(string message) { Console.WriteLine($"Current conditions display: {message}"); } }
|
如果希望更懒,更伸手就来,则可以不自己定义 delegate
,而直接使用C#提供的 EventHandler
。
使用 EventHandler
除了需要自定义一个事件参数类,继承自 EventArgs
,用于封装发生变化的数据,这种方式直接使用了C#的事件处理机制,是更符合语言特性的实践方式。更加简洁,易于理解和使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class WeatherChangedEventArgs : EventArgs { public string CurrentWeather { get; set; } public WeatherChangedEventArgs(string currentWeather) { CurrentWeather = currentWeather; } } public class WeatherData { public event EventHandler<WeatherChangedEventArgs> WeatherChanged; private string currentWeather; public void SetWeather(string weather) { this.currentWeather = weather; OnWeatherChanged(new WeatherChangedEventArgs(weather)); } protected virtual void OnWeatherChanged(WeatherChangedEventArgs e) { WeatherChanged?.Invoke(this, e); } } public class CurrentConditionsDisplay { public CurrentConditionsDisplay(WeatherData weatherData) { weatherData.WeatherChanged += WeatherData_WeatherChanged; } private void WeatherData_WeatherChanged(object sender, WeatherChangedEventArgs e) { Console.WriteLine($"Current conditions display: {e.CurrentWeather}"); } }
|