介绍
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种
它定义了一种 一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
理解
主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝(粉丝肯定是多个)
角色
Observer
观察者,一般是 接口
至少有一个通知方法
ConcrereObserver
观察者实现类,实现 Observer 接口
subject
主题,即:被观察者,一般 抽象类 或 普通类
ConcreteSubject
主题实现类,即:被观察者实现类,该类的状态发生改变时,给所有观察者发送通知。
被观察者有一个 集合,该集合保存所有 观察者 ,即:可以有任意数量的观察者,可以增加和删除观察者
状态,就是
boolern成员变量,false表示未通知,通知后赋值为true通知方法,给所有观察者发送通知
观察者 与 被观察者的关系
一个被观察者 对应 多个 观察者
什么是发通知?
答:就是 被观察者 调用 观察者(多个) 的某个方法
如何发通知?
答:状态发生改变后,发送通知给观察者
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<Fans> 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
