观察者模式
1.一对多的依赖关系,一变化多感知
2.代码
c++:
1 //observer c++ 2 #include <iostream> 3 #include <list> 4 using namespace std; 5 6 //Observer 7 class Observer{ 8 public: 9 virtual void update(float temp,float humidity,float pressure) = 0; 10 }; 11 12 //DisplayElement 13 class DisplayElement{ 14 public: 15 virtual void display() = 0; 16 }; 17 18 //Subject 19 class Subject{ 20 public: 21 virtual void registerObserver(Observer* o) = 0; 22 virtual void removeObserver (Observer* o) = 0; 23 virtual void notifyObservers () = 0; 24 25 }; 26 27 class WeatherData : public Subject{ 28 public: 29 WeatherData(){} 30 void registerObserver(Observer* o){ 31 if(o) 32 observers.push_back(o); 33 } 34 void removeObserver(Observer* o){ 35 auto it = observers.begin(); //begin()返回的类型由对象是否为const决定 36 while(it != observers.end()){ //只要执行了erase(it),那么it就会变得无效, 37 //那么执行it++就肯定会出错,erase 返回指向删除后位置,要写 it = erase(it); 38 if(*it == o) 39 it = observers.erase(it); 40 } 41 } 42 void notifyObservers(){ 43 for(Observer* obs : observers){ 44 obs->update(temperature,humidity,pressure); 45 } 46 } 47 void measurementsChanged(){ 48 notifyObservers(); 49 } 50 void setMeasurements(float temperature,float humidity,float pressure){ 51 this->temperature = temperature; 52 this->humidity = humidity; 53 this->pressure = pressure; 54 measurementsChanged(); 55 } 56 57 private: 58 list<Observer*> observers; 59 float temperature; 60 float humidity; 61 float pressure; 62 }; 63 64 //Current Display 65 class CurrentConditonDisplay : public Observer,DisplayElement{ 66 67 public: 68 //抽象类型不能用作形参类型,函数返回类型 69 CurrentConditonDisplay(WeatherData* weatherData){ 70 this->weatherData = weatherData; 71 weatherData->registerObserver(this); 72 } 73 void update(float temperature,float humidity,float pressure){ 74 this->temperature = temperature; 75 this->humidity = humidity; 76 display(); 77 } 78 79 void display(){ 80 cout<<"\r\nCurrent condition:"<<temperature<<"F degree and "<<humidity<<"%humidity"; 81 } 82 83 private: 84 float temperature; 85 float humidity; 86 WeatherData* weatherData; 87 }; 88 89 // 90 int main(){ 91 WeatherData* weatherData = new WeatherData(); //WeatherData 92 CurrentConditonDisplay* currentDisplay = new CurrentConditonDisplay(weatherData); 93 94 weatherData->setMeasurements(80,65,26.3f); 95 weatherData->setMeasurements(89,61,30.3f); 96 97 //remove 98 weatherData->removeObserver(currentDisplay); 99 weatherData->setMeasurements(76,67,12.3f); 100 101 return 0; 102 }
java:
(1)
1 import java.util.ArrayList; 2 3 //Subject 4 interface Subject{ 5 public void registerObserver(Observer o); 6 public void removeObserver(Observer o); 7 public void notifyObservers(); 8 } 9 10 class WeatherData implements Subject{ 11 private ArrayList<Observer> observers; 12 private float temperature; 13 private float humidity; 14 private float pressure; 15 16 public WeatherData(){ 17 observers = new ArrayList<Observer>(); 18 } 19 //+ 20 public void registerObserver(Observer o){ 21 observers.add(o); 22 } 23 //- 24 public void removeObserver(Observer o){ 25 int i = observers.indexOf(o); 26 if(i >= 0) 27 observers.remove(i); 28 } 29 // ))) 30 public void notifyObservers(){ 31 for (Observer observer : observers){ 32 observer.update(temperature,humidity,pressure); 33 } 34 } 35 public void measurementsChanged(){ 36 notifyObservers(); 37 } 38 public void setMeasurements(float temperature,float humidity,float pressure){ 39 this.temperature = temperature; 40 this.humidity = humidity; 41 this.pressure = pressure; 42 measurementsChanged(); 43 } 44 } 45 //Observer 46 interface Observer{ 47 public void update(float temp,float humidity,float pressure); 48 } 49 50 interface DisplayElement{ 51 public void display(); 52 } 53 54 //Current Display 55 class CurrentConditonDisplay implements Observer,DisplayElement{ 56 private float temperature; 57 private float humidity; 58 private Subject weatherData; //Subject 59 60 public CurrentConditonDisplay(Subject weatherData){ 61 this.weatherData = weatherData; 62 weatherData.registerObserver(this); 63 } 64 public void update(float temperature,float humidity,float pressure){ 65 this.temperature = temperature; 66 this.humidity = humidity; 67 display(); 68 } 69 70 public void display(){ 71 System.out.println("\r\nCurrent condition:" + temperature + "F degree and " + humidity + "%humidity"); 72 } 73 } 74 public class WeatherStation{ 75 public static void main(String[] args){ 76 WeatherData weatherData = new WeatherData(); //WeatherData 77 CurrentConditonDisplay currentDisplay = new CurrentConditonDisplay(weatherData); 78 //CurrentConditonDisplay currentDisplay2 = new CurrentConditonDisplay(weatherData); 79 80 weatherData.setMeasurements(80,65,26.3f); 81 weatherData.setMeasurements(89,61,30.3f); 82 83 //remove 84 weatherData.removeObserver(currentDisplay); 85 weatherData.setMeasurements(76,67,12.3f); 86 } 87 }
(2)用内置Observable
1 //use java Observable 2 //Observable is a class not interface 3 import java.util.Observable; 4 import java.util.Observer; 5 6 class WeatherData extends Observable{ 7 private float temperature; 8 private float humidity; 9 private float pressure; 10 11 public WeatherData(){} 12 public void measurementsChanged(){ 13 setChanged(); 14 notifyObservers(); 15 } 16 public void setMeasuremants(float temperature,float humidity,float pressure){ 17 this.temperature = temperature; 18 this.humidity = humidity; 19 this.pressure = pressure; 20 measurementsChanged(); 21 } 22 public float getTempreature(){ 23 return temperature; 24 } 25 public float getHumidity(){ 26 return humidity; 27 } 28 public float getPressure(){ 29 return pressure; 30 } 31 } 32 33 // 34 interface DisplayElement { 35 public void display(); 36 } 37 38 class CurrentConditionDisplay implements Observer,DisplayElement{ 39 Observable observable; 40 private float temperature; 41 private float humidity; 42 43 public CurrentConditionDisplay(Observable observable){ 44 this.observable = observable; 45 observable.addObserver(this); 46 } 47 @Override 48 public void update(Observable obs,Object arg){ 49 if(obs instanceof WeatherData){ 50 WeatherData weatherData = (WeatherData)obs; 51 this.temperature = weatherData.getTempreature(); 52 this.humidity = weatherData.getHumidity(); 53 display(); 54 } 55 } 56 public void display(){ 57 System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); 58 } 59 } 60 61 public class WeatherStationObable{ 62 public static void main(String[] args){ 63 WeatherData weatherData = new WeatherData(); 64 CurrentConditionDisplay display_1 = new CurrentConditionDisplay(weatherData); 65 66 weatherData.setMeasuremants(21,34,65); 67 weatherData.setMeasuremants(31,42,75); 68 } 69 }
3.杂注:
(1) 有多个观察者时,不可依赖特定通知顺序
(2)针对接口编程,不针对实现
(3)为对象间松耦合设计而努力
(4)找出变化的方面,和不变的方面分离
变化:主题的状态,观察者数量,类型;可以改变依赖于主题状态的对象,却不改变主题。
(5)多用组合,少用继承
将观察者组合进主题中,对象间关系不是继承产生,在运行中组合产生。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通