观察者模式
分享视频链接:https://www.bilibili.com/video/BV1PC4y1x7ig/
以下是文字稿和幻灯片:
大家好,我今天给大家分享的是观察者模式:
在生活中我们有一个很常见的场景,也就是在等红绿灯的时候
这里面呢,观察者就是我们的汽车,而观察目标就是我们的交通信号灯。
他们之间是一个一对多的关系,建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应
那我们来看看是什么是观察者模式:
观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
观察者模式 UML类图:
模式包含4个角色:
Subject: 目标
ConcreteSubject:具体目标
Observer: 观察者
ConcreteObserver: 具体观察者
我们下面来看一下代码实践:
一个天气预报系统,凡是订阅了改天气预报的,当天气发生改变的时候就把通知发送给所有订阅该天气预报的人。如兽人族(Orcs)和霍比特人(Hobitts)订阅了该天气预报系统,当天气从晴变成雨天的时候,兽人族和霍比特人就收到了天气变成雨天的通知。 如果还有其他订阅了该天气预报的如人族(Terran),只需要在WeatherObserver中加入该人族(Terran)订阅者,这样当天气发生改变的时候,人族也会收到天气通知。
1 //先定义天气类型(WeatherType.java),定义为枚举类型(sunny,rainny,windy,clod) 2 public enum WeatherType { 3 SUNNY,WINDY,CLOD,RAINY; 4 5 @Override 6 public String toString(){ 7 return this.name().toLowerCase(); 8 } 9 } 10 11 //再将订阅者抽象成一个接口(WeatherObserver.java),所有订阅天气预报系统的必须实现这个接口 12 public interface WeatherObserver { 13 public void Upadate(WeatherType currentWeather); 14 } 15 16 //天气类(Weather)负责定义数据结构来接收订阅者和通知更新订阅者天气变化。使用List<WeatherObserver>来接收订阅者,定义方法addObserver来接收新的订阅者和notifyAllObsever方法来更新订阅者天气状态。 17 import java.util.ArrayList; 18 import java.util.List; 19 20 public class Weather { 21 private WeatherType currentWeather; 22 private List<WeatherObserver> observers; 23 24 public Weather(){ 25 observers=new ArrayList<>(); 26 currentWeather=WeatherType.SUNNY; 27 } 28 29 public void addObservers(WeatherObserver observer){ 30 observers.add(observer); 31 } 32 33 public void removeObservers(WeatherObserver observer){ 34 observers.remove(observer); 35 } 36 37 38 public void timePasses(){ 39 WeatherType[] enumValues=WeatherType.values(); 40 /* for(WeatherType type:enumValues){ 41 System.out.println(type); 42 }*/ 43 //改变天气,让天气的enum类型往后推一个 44 currentWeather=enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; 45 System.out.println("The weather change to "+currentWeather); 46 notifyAllObserver(); 47 } 48 49 public void notifyAllObserver(){ 50 for(WeatherObserver obs: observers){ 51 obs.Upadate(currentWeather); 52 } 53 } 54 } 55 56 //添加两个订阅天气预报的“人”,一个兽族(Orcs.java)一个霍比特人(Hobitts.java)。 如上面所说,要订阅该天气预报必须实现WeatherOberver接口。 57 public class Orcs implements WeatherObserver{ 58 59 @Override 60 public void Upadate(WeatherType currentWeather) { 61 switch(currentWeather){ 62 case CLOD: 63 System.out.println("The orcs are freezing cold"); 64 break; 65 case SUNNY: 66 System.out.println("The sun hurts the orcs' eyes."); 67 break; 68 case RAINY: 69 System.out.println("The orcs are dripping wet."); 70 break; 71 case WINDY: 72 System.out.println("The orc smell almost vanishes in the wind."); 73 default: 74 break; 75 } 76 } 77 78 79 public class Hobbits implements WeatherObserver{ 80 81 @Override 82 public void Upadate(WeatherType currentWeather) { 83 switch(currentWeather){ 84 case CLOD: 85 System.out.println("The Hobbits are freezing cold"); 86 break; 87 case SUNNY: 88 System.out.println("The sun hurts the Hobbits' eyes."); 89 break; 90 case RAINY: 91 System.out.println("The Hobbits are dripping wet."); 92 break; 93 case WINDY: 94 System.out.println("The Hobbits smell almost vanishes in the wind."); 95 default: 96 break; 97 } 98 } 99 } 100 101 //测试 102 public class APP { 103 public static void main(String[] args){ 104 Weather weather=new Weather(); 105 weather.addObservers(new Orcs()); 106 weather.addObservers(new Hobbits()); 107 108 //weather.addObservers(new Terran()); 109 110 weather.timePasses(); 111 112 //weather.timePasses(); 113 114 } 115 }
观察者模式可以实现表示层和数据逻辑层的分离。
观察者模式在观察目标和观察者之间建立一个抽象的耦合。
观察者模式支持广播通信。
将所有的观察者都通知到会花费很多时间可能存在循环依赖
谢谢大家