观察者模式(Java)
观察者模式也称发布者模式,它是一种在项目中经常使用的模式。
一.观察者模式的现实场景
卢康很喜欢玩微信,他喜欢浏览朋友圈来了解朋友圈里面的人的最近情况,以及把自己周边发生的事情分享給其他人看。今天早上在他上班的路上发生了一件事情,有个老人倒在地上,旁边的行人纷纷绕开老人离开,没有一个人主动扶起老人。卢康把这个场景拍了下来,上传到朋友圈,刚上传上去就有人回复了。习伟回复说:现在老人到底谁敢扶啊,你上去扶老人就被讹上了,到时候你都说不清楚。蔡良说:卢康你怎么只拍照而不去扶老人啊,我们社会需要多一些正能量,少一些冷漠状态。
上面场景中,卢康在微信上发状态,然后朋友给他回复信息状态,这样的场景类似于设计模式中的观察者模式。这里卢康的朋友的观察者,而卢康是被观察者,只要卢康的朋友圈有什么消息,观察者就能知道。
这也类似我java的接口回调,进行监听后,就能在触发的时候收到对应的监听内容。
二.观察者模式(Observer Pattern)的定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,所有依赖于它的对象都会得到通知并被自动更新。
三.观察者模式的类图
四.观察者模式的四个角色
1. 抽象主题(Subject)角色
该角色又称为“被观察者”,可以增加和删除观察者对象。
2.抽象观察者(Observer)角色
该角色为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
3.具体主题(Concrete Subject)角色
该角色又称为“具体被观察者”,他将有关状态存入具体观察者对象,在具体主题的内部状态改变时,給所有登记过的观察者发出通知。
4. 具体观察者(Concrete Observer)角色
该角色实现抽象观察者所要求的更新接口,以便使自身的状态与主题的状态相协调。
五.观察者模式的优缺点
观察者模式中的优点
1.观察者和被观察者之间是抽象耦合。被观察者并不全部知道所有的具体观察者,他只知道它们有一个共同的接口。比如现实场景中,卢康知道自己的朋友圈信息被看到,并不知道所有看他信息的人。
2. 观察者模式支持广播通信。
观察者模式的缺点
1.如果一个主题有过个直接或间接的观察者,则通知所有的观察者会花费很多的时间,而且它的开发和调试都比较复杂。
2.如果在主题之间有循环依赖的华,被观察者会触发它们进行循环调用,导致系统崩溃。
3.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递的顺序执行。
4.观察者模式没有提供相应的机制使观察者知道所观察的对象是怎么发生变化的,只知道结果变化了。
六.观察者模式的注意事项
观察者模式使用注意的事项:
1. 广播链问题。一个观察者既可以有双重身份,它既可以是观察者,也可以是被观察者,逻辑复杂的时候,可维护性就比较低了。所以一般一个观察者模式中最多出现一个双重身份的对象就够了,较易控制。
2.异步处理的问题。异步处理就要考虑线程安全和队列的问题。
七.观察者模式的示例
这里使用上面的现实场景做代码示例。
示例的类图
示例的代码
1.抽象主题类,朋友圈ITalkSubject
package p19_observer;
/**
* 抽象主题,朋友圈
*/
public interface ITalkSubject {
//让某些人看见我的朋友圈
void registerObserver(ITalkObserver observer);
//不然某些人看见我的朋友圈
void deleteObserver(ITalkObserver observer);
//刷新,让朋友知道
void notifyObserver();
}
2.抽象观察者ITalkObserver
package p19_observer;
/**
* 抽象观察者,看朋友圈的人
*/
public interface ITalkObserver {
//更新朋友圈
void updateTalk(String msg);
}
3.具体朋友圈ConcreteTalkSubject
package p19_observer;
import java.util.ArrayList;
import java.util.List;
/**
* 具体的朋友圈
*/
public class ConcreteTalkSubject implements ITalkSubject {
//观察者集合,管理那些人能看我的朋友圈
private List<ITalkObserver> observerList = new ArrayList<>();
//朋友圈消息
private String msg;
//增加可以看我朋友圈的人
@Override
public void registerObserver(ITalkObserver observer) {
observerList.add(observer);
}
//删除可以看我朋友圈的人
@Override
public void deleteObserver(ITalkObserver observer) {
observerList.remove(observer);
}
//刷新,让看我朋友圈的人都知道:我更新信息了
@Override
public void notifyObserver() {
for (int i = 0; i < observerList.size(); i++) {
observerList.get(i).updateTalk(msg);//給每一个观察者刷新一下
}
}
//设置朋友圈信息
public void setMessage(String msg) {
this.msg = msg;
notifyObserver();//刷新
}
}
4.具体观察者,看朋友圈的人ConcreteTalkObserver
package p19_observer;
/**
* 具体的看朋友圈的人
*/
public class ConcreteTalkObserver implements ITalkObserver {
//姓名
private String name;
//构造方法,传入姓名
public ConcreteTalkObserver(String name){
this.name=name;
}
//关注的朋友圈,数据更新了
@Override
public void updateTalk(String msg) {
System.out.println(name+" 收到一条朋友圈的更新:"+msg);
}
}
5.测试类TalkDemo
package p19_observer;
/**
* 测试类
*/
public class TalkDemo {
public static void main(String[] arg) {
//创建一个朋友圈
ConcreteTalkSubject talkSubject = new ConcreteTalkSubject();
//看朋友圈的人
ITalkObserver talk1 = new ConcreteTalkObserver("习大");
ITalkObserver talk2 = new ConcreteTalkObserver("蔡亮");
//把看朋友圈的人添加到朋友圈中
talkSubject.registerObserver(talk1);
talkSubject.registerObserver(talk2);
//添加朋友圈信息,别人就可以看到
talkSubject.setMessage("今天看到一个老大爷摔倒在地上,没有人去扶老大爷!");
}
}
程序运行结果;
--------------------- 本文来自 峥嵘life 的**** 博客 ,全文地址请点击:https://blog.****.net/wenzhi20102321/article/details/80330335?utm_source=copy