设计模式-观察者模式-java 作者:马育民 • 2023-02-06 16:49 • 阅读:10057 # 介绍 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种 它定义了一种 **一对多的依赖关系**,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。 ### 理解 主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝(粉丝肯定是多个) # 角色 [![](/upload/0/0/1IX4v6ycbfb5.png)](/upload/0/0/1IX4v6ycbfb5.png) ## Subject 主题,即:被观察者,Observable,一般是 **抽象类** 或 **普通类** - 把所有 **观察者** 保存在一个 **集合** 里,即:可以有任意数量的观察者,可以增加和删除观察者 - 主题的状态,就是 成员变量,一般是 `boolean` 类型 - 通知方法,给所有观察者发送通知 #### 什么是发通知? 答:就是 被观察者 调用 观察者(多个) 的某个方法 #### 如何发通知? 答:状态发生改变后,发送通知给观察者 ## ConcreteSubject 具体的被观察者类,该类的状态发生改变时,给所有观察者发送通知。 ## Observer 观察者,一般是 **接口** 至少有一个通知方法 ## ConcrereObserver 具体观察者,观察者实现类,实现 `Observer` 接口 通知方法:被观察者通知观察者时,其实就是调用该方法 # java 内置观察者相关类 - 观察者:实现 `java.util.Observer` 接口,实现 `update()` 方法,当 被观察者 通知 观察者时,会调用该方法 - 被观察者类:需要继承 `java.util.Observable` 类 - `addObserver()` 方法添加观察者 - 当被观察者发生了改变,就需要调用 `setChanged()` 方法,将标志变量 `changed` 修改为 `true` - 使用`notifyObservers()` 方法通知所有的观察者,即:调用 观察者的 `update()` 方法。并将标志变量 `changed` 置回原值 `false` **关键:**必须先调用 `setChanged()` 方法,否则不会通知 # 例子 主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝 使用 java自带类实现 ### 观察者实现类 粉丝是观察者 ``` package 观察者.java自带类; import 观察者.Fans; import java.util.Observable; import java.util.Observer; public class FansImpl implements Observer { private String name; public FansImpl(String name) { this.name = name; } // 被观察者发通知时,调用该方法 @Override public void update(Observable o, Object msg) { System.out.println(msg); Zhubo zhubo = (Zhubo)o; System.out.println(name+"说:不学了,看 "+zhubo.getName() + "直播"); } } ``` ### 被观察者类 主播是被观察者 ``` package 观察者.java自带类; import java.util.Observable; /** * 主播类,相当于被观察者 */ public class Zhubo extends Observable { private String name; public Zhubo(String name) { this.name = name; } /** * 开播,也就是修改状态 */ public void kaibo(){ // ※※※※必须先调用该方法,否则通知方法无效※※※ setChanged(); // 发通知 notifyObservers(name+"开播啦,快来呀!"); } public String getName() { return name; } } ``` ### 测试类 ``` package 观察者.java自带类; import java.util.Observer; public class Main { public static void main(String[] args) { Zhubo lilei = new Zhubo("李雷"); Observer hanmeimei = new FansImpl("韩梅梅"); Observer lili = new FansImpl("lili"); Observer lucy = new FansImpl("lucy"); lilei.addObserver(hanmeimei); lilei.addObserver(lili); lilei.addObserver(lucy); System.out.println("观察者数量:"+lilei.countObservers()); lilei.kaibo(); // 开播 System.out.println("------------ 移除 lucy--------"); lilei.deleteObserver(lucy); System.out.println("观察者数量:"+lilei.countObservers()); lilei.kaibo(); // 必须先开播,否则不会发送通知 lilei.notifyObservers(); } } ``` 执行结果: ``` 观察者数量:3 李雷开播啦,快来呀! lucy说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! lili说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! 韩梅梅说:老娘不学了,看 李雷直播 ------------ 移除 lucy-------- 观察者数量:2 李雷开播啦,快来呀! lili说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! 韩梅梅说:老娘不学了,看 李雷直播 ``` # 例子 主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝 完全自定义,可更好的理解细节 ### 观察者接口 粉丝是观察者 ``` package 观察者; /** * 粉丝接口(相当于观察者接口) */ public interface Fans { /** * 主播(被观察者)通知粉丝(被观察者),就是调用该方法 * @param zhubo * @param msg */ public void jinZhiBoJian(Zhubo zhubo,String msg); } ``` ### 观察者实现类 ``` package 观察者; public class FansImpl implements Fans{ private String name; public FansImpl(String name) { this.name = name; } @Override public void jinZhiBoJian(Zhubo zhubo, String msg) { System.out.println(msg); System.out.println(name+"说:老娘不学了,看 "+zhubo.getName() + "直播"); } } ``` ### 被观察者类 主播是被观察者 ``` package 观察者; import java.util.ArrayList; import java.util.List; /** * 主播类,相当于被观察者 */ public class Zhubo { private String name; /** * 该集合保存粉丝(粉丝相当于观察者) */ private List fansList = new ArrayList(); /** * 是否开播(相当于被观察者中的状态) */ private boolean isKaibo = false; public Zhubo(String name) { this.name = name; } /** * 添加粉丝(观察者) * @param fans */ public void addFans(Fans fans){ fansList.add(fans); } /** * 删除粉丝(观察者) * @param fans */ public void removeFans(Fans fans){ fansList.remove(fans); } public void clearFans(){ fansList.clear(); } /** * 开播,也就是修改状态 */ public void kaibo(){ this.isKaibo = true; } /** * 停播,也就是重置状态为初始值 */ public void tingbo(){ this.isKaibo = false; } public void noticeAll(){ // 开播(状态为true)时,才会发通知 if(!isKaibo){ return; } for(Fans item:fansList){ item.jinZhiBoJian(this,name+"开播啦,快来呀!"); } tingbo(); } public String getName() { return name; } } ``` ### 测试类 ``` package 观察者; public class Main { public static void main(String[] args) { Zhubo lilei = new Zhubo("李雷"); Fans hanmeimei = new FansImpl("韩梅梅"); Fans lili = new FansImpl("lili"); Fans lucy = new FansImpl("lucy"); lilei.addFans(hanmeimei); lilei.addFans(lili); lilei.addFans(lucy); lilei.kaibo(); // 必须先开播,否则不会发送通知 lilei.noticeAll(); System.out.println("------------ 移除 lucy--------"); lilei.removeFans(lucy); lilei.kaibo(); // 必须先开播,否则不会发送通知 lilei.noticeAll(); } } ``` 执行结果: ``` 李雷开播啦,快来呀! 韩梅梅说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! lili说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! lucy说:老娘不学了,看 李雷直播 ------------ 移除 lucy-------- 李雷开播啦,快来呀! 韩梅梅说:老娘不学了,看 李雷直播 李雷开播啦,快来呀! lili说:老娘不学了,看 李雷直播 ``` https://blog.csdn.net/itachi85/article/details/50773358 原文出处:http://malaoshi.top/show_1IX4v6dioI0Y.html