设计模式——观察者模式
观察者模式(又称发布/订阅者模式)提供了避免组件之间紧密耦合的一种方法,将观察者和被观察者的对象分开。在该模式中,一个对象通过添加一个方法使自身变得可观察。当被观察的对象更改时,它会通知已注册的观察者,这些观察者收到通知后所执行的操作与被观察者的对象无关。这种模式使得对象可以互相对话,而不必了解原因。
添加和删除观察者的主动权在被观察者一方。
观察者模式在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
四个角色
1)抽象被观察者角色:一个抽象主题,把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供接口方法,可以增加、删除、通知观察者角色。一般用一个抽象类或者接口来实现。
2)抽象观察者角色:为所有的具体观察者定义一个接口方法,在得到主题通知是更新自己,相当于一个set方法。
3)具体被观察者角色:具体的主题,将有关状态存入具体观察者对象,当具体主题的内部状态改变时,所有登记注册的观察者发出通知。
4)具体观察者角色:具体观察者,实现了抽象观察者中的更新方法,从而使自身的状态与主题的状态相协调。
第一个场景例子:有一个微信公众号服务,不定时发布一些消息,关注公众号就可以收到推送消息,取消关注就收不到推送消息。
角色:被观察者接口
1 package com.test.observer; 2 3 public interface Observarable { 4 /* 5 被观察者接口 6 声明了添加、删除、通知观察者的方法 7 */ 8 public abstract void addObserver(Observer obs); 9 public abstract void removeObserver(Observer obs); 10 public abstract void notifyObserver(); 11 }
角色:观察者接口
1 package com.test.observer; 2 3 public interface Observer { 4 /* 5 观察者接口 6 声明了一个方法,当被观察者调用notifyObserver()方法时,观察者的update()方法会被回调。 7 */ 8 public abstract void update(String message); 9 }
角色:实现被观察者接口的具体被观察者类
1 package com.test.observer; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class WechatServer implements Observarable { 7 /* 8 定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现, 9 同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可。 10 */ 11 private List<Observer> list; 12 private String message; 13 public WechatServer(){ 14 this.list = new ArrayList<Observer>(); 15 } 16 @Override 17 public void addObserver(Observer obs) { 18 this.list.add(obs); 19 } 20 21 @Override 22 public void removeObserver(Observer obs) { 23 if (!this.list.isEmpty()) { 24 this.list.remove(obs); 25 } 26 } 27 28 @Override 29 public void notifyObserver() { 30 for (Observer aList : list) { 31 aList.update(message); 32 } 33 } 34 35 public void setInfromation(String str){ 36 this.message = str; 37 System.out.println("微信服务更新信息素: " + str); 38 notifyObserver(); 39 } 40 }
角色:实现观察者接口的观察者类
1 package com.test.observer; 2 3 public class User implements Observer { 4 /* 5 观察者,实现了update()方法 6 */ 7 private String name; 8 private String message; 9 10 public User(String name){ 11 this.name = name; 12 } 13 @Override 14 public void update(String message) { // 功能类似于set方法 15 this.message = message; 16 read(); 17 } 18 19 public void read(){ 20 System.out.println(this.name + "收到推送的消息: " + this.message); 21 } 22 }
测试
1 package com.test.observer; 2 3 public class TestObserver { 4 public static void main(String[] args){ 5 WechatServer ws = new WechatServer(); 6 Observer userZhang = new User("Zhang"); 7 Observer userLi = new User("Li"); 8 Observer userZhao = new User("Zhao"); 9 ws.addObserver(userZhang); 10 ws.addObserver(userLi); 11 ws.addObserver(userZhao); 12 ws.setInfromation("Java是世界上最好的语言"); 13 System.out.println("----------------------------"); 14 ws.removeObserver(userZhang); 15 ws.setInfromation("C语言是世界最好的语言"); 16 } 17 }
测试结果
第二个场景例子:天气预报
角色:被观察者接口
1 package coding.com.test.observer2; 2 3 public interface Subject { 4 public abstract void addObserver(Observer obs); 5 public abstract void removeObserver(Observer obs); 6 public abstract void notifyObserver(); 7 }
角色:观察者接口
1 package coding.com.test.observer2; 2 3 public interface Observer { 4 public abstract void update(float temp); 5 }
角色:具体被观察者
1 package coding.com.test.observer2; 2 3 import java.util.List; 4 import java.util.ArrayList; 5 6 public class WeatherServer implements Subject { 7 private List<Observer> list = new ArrayList<>(); 8 private float temp; 9 10 @Override 11 public void addObserver(Observer obs) { 12 list.add(obs); 13 } 14 15 @Override 16 public void removeObserver(Observer obs) { 17 if (!list.isEmpty()){ 18 list.remove(obs); 19 } 20 } 21 22 @Override 23 public void notifyObserver() { 24 for (Observer aList : list){ 25 aList.update(temp); 26 } 27 } 28 public void setTemp(float temp){ 29 this.temp = temp; 30 notifyObserver(); 31 } 32 }
角色:具体观察者1
1 package coding.com.test.observer2; 2 3 public class WeatherDisplay1 implements Observer { 4 private float temp; 5 @Override 6 public void update(float temp) { 7 this.temp = temp; 8 showWeather(); 9 } 10 public void showWeather(){ 11 System.out.println("display1: " + temp); 12 } 13 }
角色:具体观察者2
1 package coding.com.test.observer2; 2 3 public class WeatherDisplay2 implements Observer { 4 private float temp; 5 @Override 6 public void update(float temp) { 7 this.temp = temp; 8 showWeather(); 9 } 10 11 public void showWeather(){ 12 System.out.println("Display2; " + temp); 13 } 14 }
测试
1 package coding.com.test.observer2; 2 3 public class TestObserver { 4 public static void main(String[] args){ 5 WeatherServer ws = new WeatherServer(); 6 WeatherDisplay1 wd1 = new WeatherDisplay1(); 7 WeatherDisplay2 wd2 = new WeatherDisplay2(); 8 ws.addObserver(wd1); 9 ws.addObserver(wd2); 10 ws.setTemp(12.57f); 11 } 12 }
测试结果