设计模式-观察者模式
观察者模式
一.什么是观察者模式?
观察者模式,有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
二.观察者模式有哪些角色?
1. 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里(集合),每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
主题的功能:RegisterObserver(注册观察者),RemoveObserver(移除观察者),NotifyObservers(通知观察者)
2. 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
3.抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
观察者的功能:Update(更新)
4.具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
三.观察者模式的优缺点?
优点:
1.当被观察者状态发生改变时,会通知所有的观察者,使他们自动更新自己(广播通信);
2.解耦,让依赖的双方都依赖抽象,而不是依赖具体实现;
缺点:
1.当出现循环,容易导致系统崩溃;
四.实现方式:
1.接口:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ObServer 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 var weather = new WeatherData(); 15 var curent = new CurrentConditionDisplay(); 16 weather.RegisterObserver(curent); 17 var curent2 = new CurrentConditionDisplay2(); 18 weather.RegisterObserver(curent2); 19 weather.SetData(new WeatherMessage() 20 { 21 Temperature = 1, 22 Humidity = 2, 23 Pressure = 3 24 }); 25 26 weather.SetData(new WeatherMessage() 27 { 28 Temperature = 2, 29 Humidity = 3, 30 Pressure = 4 31 }); 32 Console.ReadKey(); 33 } 34 } 35 36 public class WeatherData : ISubject 37 { 38 public WeatherData() 39 { 40 _observerList = new List<IObserver>(); 41 } 42 private readonly List<IObserver> _observerList; 43 private WeatherMessage _message; 44 45 public void SetData(WeatherMessage message) 46 { 47 _message = message; 48 NotifyObservers(); 49 } 50 51 public void NotifyObservers() 52 { 53 for (int i = 0; i < _observerList.Count; i++) 54 { 55 var observer = _observerList[i]; 56 observer.Update(_message); 57 } 58 } 59 60 public void RegisterObserver(IObserver observer) 61 { 62 _observerList.Add(observer); 63 } 64 65 public void RemoveObserver(IObserver observer) 66 { 67 if (_observerList.Contains(observer)) 68 { 69 _observerList.Remove(observer); 70 } 71 } 72 } 73 74 public class CurrentConditionDisplay : IObserver 75 { 76 private WeatherMessage _message; 77 78 public void Update(WeatherMessage message) 79 { 80 _message = message; 81 Console.WriteLine($"温度:{_message.Temperature},湿度:{_message.Humidity},气压:{_message.Pressure}"); 82 } 83 } 84 85 public class CurrentConditionDisplay2 : IObserver 86 { 87 private WeatherMessage _message; 88 89 public void Update(WeatherMessage message) 90 { 91 _message = message; 92 Console.WriteLine($"温度:{_message.Temperature},湿度:{_message.Humidity},气压:{_message.Pressure}"); 93 } 94 } 95 96 /// <summary> 97 /// 主题接口 98 /// </summary> 99 public interface ISubject 100 { 101 void RegisterObserver(IObserver observer); 102 void RemoveObserver(IObserver observer); 103 void NotifyObservers(); 104 } 105 106 /// <summary> 107 /// 观察者接口 108 /// </summary> 109 public interface IObserver 110 { 111 void Update(WeatherMessage message); 112 } 113 114 public class WeatherMessage 115 { 116 /// <summary> 117 /// 温度 118 /// </summary> 119 public float Temperature { get; set; } 120 121 /// <summary> 122 /// 湿度 123 /// </summary> 124 public float Humidity { get; set; } 125 126 /// <summary> 127 /// 气压 128 /// </summary> 129 public float Pressure { get; set; } 130 } 131 132 }
2.委托

1 using System; 2 using System.Collections.Generic; 3 using System.Data.Odbc; 4 using System.Linq; 5 using System.Reflection; 6 using System.Text; 7 using System.Threading; 8 using System.Threading.Tasks; 9 10 namespace ObServer 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 var sub = new Subject(); 17 var ob = new Observer(); 18 sub.NotifyObservers += ob.Update;//观察者,即使没有观察者程序是不影响的(解耦) 19 var ob2 = new Observer(); 20 sub.NotifyObservers += ob2.Update; 21 sub.SetData(new WeatherMessage() 22 { 23 Temperature = 1, 24 Humidity = 2, 25 Pressure = 3 26 }); 27 28 sub.SetData(new WeatherMessage() 29 { 30 Temperature = 1, 31 Humidity = 2, 32 Pressure = 3 33 }); 34 sub.Complated(); 35 Console.ReadKey(); 36 } 37 } 38 39 public class Subject 40 { 41 public delegate void UpdateHandler(WeatherMessage message); 42 public event UpdateHandler NotifyObservers; 43 public WeatherMessage _message; 44 45 public void SetData(WeatherMessage message) 46 { 47 _message = message; 48 Console.WriteLine("设置数据完成"); 49 if (NotifyObservers != null) 50 { 51 NotifyObservers(_message); 52 } 53 } 54 55 public void Complated() 56 { 57 NotifyObservers = null; 58 Console.WriteLine("完成"); 59 } 60 } 61 62 public class Observer 63 { 64 public WeatherMessage _message; 65 public void Update(WeatherMessage message) 66 { 67 _message = message; 68 Console.WriteLine($"温度:{_message.Temperature},湿度:{_message.Humidity},气压:{_message.Pressure}"); 69 } 70 } 71 72 public class Observer2 73 { 74 public WeatherMessage _message; 75 public void Update(WeatherMessage message) 76 { 77 _message = message; 78 Console.WriteLine($"温度:{_message.Temperature},湿度:{_message.Humidity},气压:{_message.Pressure}"); 79 } 80 } 81 82 public class WeatherMessage 83 { 84 /// <summary> 85 /// 温度 86 /// </summary> 87 public float Temperature { get; set; } 88 89 /// <summary> 90 /// 湿度 91 /// </summary> 92 public float Humidity { get; set; } 93 94 /// <summary> 95 /// 气压 96 /// </summary> 97 public float Pressure { get; set; } 98 } 99 100 }
3.使用.net的类库:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace ObServer 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 var weather = new Observable(); 15 var ob = new Observer(); 16 weather.Subscribe(ob); 17 var ob2 = new Observer(); 18 weather.Subscribe(ob2); 19 weather.SetData(new WeatherMessage() 20 { 21 Temperature = 1, 22 Humidity = 2, 23 Pressure = 3 24 }); 25 weather.SetData(new WeatherMessage() 26 { 27 Temperature = 2, 28 Humidity = 3, 29 Pressure = 4 30 }); 31 weather.Completed(); 32 Console.ReadKey(); 33 } 34 } 35 36 /// <summary> 37 /// 主题 38 /// </summary> 39 public class Observable : IObservable<WeatherMessage>, IDisposable 40 { 41 public Observable() 42 { 43 _observerList = new List<IObserver<WeatherMessage>>(); 44 } 45 46 private readonly List<IObserver<WeatherMessage>> _observerList; 47 private IObserver<WeatherMessage> _observer; 48 private WeatherMessage _message; 49 public IDisposable Subscribe(IObserver<WeatherMessage> observer) 50 { 51 _observer = observer; 52 _observerList.Add(observer); 53 return this; 54 } 55 56 public void Dispose() 57 { 58 if (_observerList != null) 59 { 60 _observerList.Remove(_observer); 61 } 62 } 63 64 public void SetData(WeatherMessage message) 65 { 66 _message = message; 67 foreach (var item in _observerList) 68 { 69 if (_message == null) 70 { 71 item.OnError(new Exception("出差")); 72 } 73 else 74 { 75 item.OnNext(_message); 76 item.OnCompleted(); 77 } 78 } 79 } 80 81 public void Completed() 82 { 83 _observerList.Clear(); 84 } 85 } 86 87 /// <summary> 88 /// 观察者 89 /// </summary> 90 public class Observer : IObserver<WeatherMessage> 91 { 92 public void OnCompleted() 93 { 94 Console.WriteLine("完成"); 95 } 96 97 public void OnError(Exception error) 98 { 99 Console.WriteLine(error); 100 } 101 102 public void OnNext(WeatherMessage value) 103 { 104 Console.WriteLine($"温度:{value.Temperature},湿度:{value.Humidity},气压:{value.Pressure}"); 105 } 106 } 107 108 /// <summary> 109 /// 观察者2 110 /// </summary> 111 public class Observer2 : IObserver<WeatherMessage> 112 { 113 public void OnCompleted() 114 { 115 Console.WriteLine("完成"); 116 } 117 118 public void OnError(Exception error) 119 { 120 Console.WriteLine(error); 121 } 122 123 public void OnNext(WeatherMessage value) 124 { 125 Console.WriteLine($"温度:{value.Temperature},湿度:{value.Humidity},气压:{value.Pressure}"); 126 } 127 } 128 129 public class WeatherMessage 130 { 131 /// <summary> 132 /// 温度 133 /// </summary> 134 public float Temperature { get; set; } 135 136 /// <summary> 137 /// 湿度 138 /// </summary> 139 public float Humidity { get; set; } 140 141 /// <summary> 142 /// 气压 143 /// </summary> 144 public float Pressure { get; set; } 145 } 146 147 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构