什么是观察者模式
1.生活中的观察者模式
老师(被观察者)在教室讲课(讲课理解为给学生发出信号),学生(观察者)要根据老师讲的内容做笔记(收到了老师的信号,开始记录)。这就是一个典型的观察者模式。
2.程序中的观察者模式
定义
观察者模式描述的是一种一对多的关系「一个被观察者对应多个观察者」,当被观察者的状态发生改变时,所有观察者都会得到通知。通俗的理解:观察者模式就是在特定的时刻「被观察者发送通知」干特定的事情「观察者收到通知处理自己相应的事件」
结构
角色 | 类别 | 说明 |
---|---|---|
Subject | 接口或抽象类 | 主题也叫被观察者 |
RealSubject | 真实的主题类 | 具体的被观察者,内部维护了观察者的列表 |
IObserver | 观察者接口或抽象类 | 抽象出观察者的接口 |
RealObserver | 具体的观察者 | 被观察者有更新,观察者立马响应更新 |
观察者模式应用
1.微信公众号推送文章
公众号为被观察者,用户为观察者,用户关注公众号(订阅事件),那么将会收到公众号文章的推送(发布消息)
3722694548-5a2675b91c83a.jpg
定义抽象的被观察者 IWxServerSubject.java
/**
*
* 定义主题「被观察者接口」,所有的公号作者共同属性「其实这里功能上微信系统的功能,直接抽象成被观察者」
*/
public interface IWxServerSubject {
// 添加观察者
void attchObserver(IObserver iObserver) ;
// 移除观察者
void detachObserver(IObserver iObserver) ;
// 通知观察者
void notifyObserver() ;
}
定义抽象的观察者接口 Observer.Java
/**
*
* 定义观察者接口,即关注公号的微信用户共同属性
*/
public interface Observer {
// 观察者收到信息,内容为 info
void reciveContent(String info) ;
}
定义具体的被观察者「公号作者 TigerChain」 TigerChainSubject.java
/**
*
* 定义一个真实的被观察者 TigerChain「公号的作者」
* 里面存了订阅 TigerChain 微信公众账号的读者
*/
public class TigerChainSubject implements IWxServerSubject {
// 订阅者列表「观察者列表」,即关注 TigerChain 公号的读者
private List<IObserver> observers = new ArrayList<>() ;
//作者更新公号的内容
private String updateContent ;
@Override
public void attchObserver(IObserver iObserver) {
observers.add(iObserver) ;
}
@Override
public void detachObserver(IObserver iObserver) {
if(observers.contains(iObserver)) {
observers.remove(iObserver);
}
}
@Override
public void notifyObserver() {
for (IObserver iObserver:observers) {
iObserver.reciveContent(updateContent);
}
}
/**
* 是否关注我的公号
* @param iObserver
* @return
*/
public boolean isAttchObserver(IObserver iObserver){
return observers.contains(iObserver) ;
}
/**
* TigerChain 在公号中发布文章
* @param updateContent
*/
public void submitContent(String updateContent){
this.updateContent = updateContent ;
this.notifyObserver();
}
}
定义一个具体的观察者「普通的微信用户」 ReaderObserver.java
/**
*
* 微信用户
*/
public class ReaderObserver implements Observer {
// 微信用户的姓名
private String name ;
public ReaderObserver(String name){
this.uname = name ;
}
@Override
public void reciveContent(String info) {
System.out.println(uname+"注意,TigerChain 发送了文章---"+info);
}
public String getUname(){
return this.name ;
}
}
接下来开始测试
/**
*
* 测试类
*/
public class Test {
public static void main(String args[]){
IWxServerSubject iWxServerSubject = new TigerChainSubject() ;
// 微信用户
ReaderObserver zhangsai = new ReaderObserver("张三") ;
ReaderObserver lisi = new ReaderObserver("李四") ;
ReaderObserver wangwu = new ReaderObserver("王五") ;
ReaderObserver zhaoLiu = new ReaderObserver("赵六") ;
// 微信用户张三关注我的公号「即订阅」
iWxServerSubject.attchObserver(zhangsai);
// 微信用户李四关注我的公号「即订阅」
iWxServerSubject.attchObserver(lisi);
// 微信用户王五关注我的公号「即订阅」
iWxServerSubject.attchObserver(wangle);
// 我「被观察者」发布了一篇文章--观察者模式
((TigerChainSubject)iWxServerSubject).submitContent("人人都会设计模式:观察者模式") ;
boolean isAttch = ((TigerChainSubject)iWxServerSubject).isAttchObserver(zhaoLiu) ;
if(!isAttch){
System.out.println(zhaoLiu.getUname()+"你好!你还没有关注 TigerChain ,请关注先,谢谢");
}
}
}
2.狼王开会
狼是群居动物,由狼王带领。冬天来了,狼得找过冬的食物,狼王组织如开了紧急会议,下面的群狼都看着狼王传递会议精神和安排任务,此时狼王就是被观察者,群狼就是观察者。
抽象被观察者功能
/**
*
* 抽象的被观察者
*/
public interface Wolf {
// 添加观察者
void attchObserver(NormalWolf observer) ;
// 移除观察者
void detchObserver(NormalWolf observer) ;
// 通知观察者
void notifyObserver(String str) ;
}
抽象观察者普通的狼 NormalWolf.java
public abstract class NormalWolf {
// 拿到被观察者的引用
protected IWolf iWolf ;
/**
* 收到狼王下达的命令
* @param str
*/
public abstract void reciveCommand(String str) ;
}
定义具体的被观察者狼王 LangWang.java
/**
* Created by TigerChain
* 狼王「被观察者,下面的狼都看狼王的眼色行事」,是一个单例模式
*/
public class LangWang implements Wolf{
private static LangWang instance ;
private LangWang(){}
public static LangWang getInstance(){
if(instance == null){
synchronized (LangWang.class){
if(instance == null){
instance = new LangWang() ;
}
}
}
return instance ;
}
// 除过狼王外的狼「观察者」
private List<NormalWolf> observers = new ArrayList<>() ;
// 狼王下达的命令
private String mingLing ;
@Override
public void attchObserver(NormalWolf observer) {
observers.add(observer);
}
@Override
public void detchObserver(NormalWolf observer) {
if(observers.contains(observer)){
observers.remove(observer) ;
}
}
@Override
public void notifyObserver(String str) {
for(NormalWolf observer:observers){
observer.reciveCommand(str);
}
}
/**
* 下达命令
* @param mingLing
*/
public void xiaDaMingling(String mingLing){
this.mingLing = mingLing ;
this.notifyObserver(mingLing);
}
}
定义一个观察者侦查狼 ZhenChaLang.java
/**
* Created by TigerChain
* 侦查狼,另一个观察者
*/
public class ZhenChaLang extends NormalWolf {
public ZhenChaLang(IWolf iWolf){
this.iWolf = iWolf ;
this.iWolf.attchObserver(this);
}
@Override
public void reciveCommand(String string) {
System.out.println("侦查狼:狼王开会传递的信息是 \n"+string);
}
}
定义另一个观察者捕猎狼 BuLieLang.java
/**
*
* 捕猎狼---观察者
*/
public class BuLieLang extends NormalWolf {
public BuLieLang(IWolf iWolf){
this.iWolf = iWolf ;
// 添加观察者,即捕猎狼放在狼王组织中
this.iWolf.attchObserver(this);
}
@Override
public void reciveCommand(String string) {
System.out.println("捕猎狼:狼王开会传递的信息是 \n"+string+"\n");
}
}
测试
/**
*
* 测试类
*/
public class Test {
public static void main(String args[]){
// 使用单例模式
LangWang langWang = LangWang.getInstance() ;
BuLieLang buLieLang = new BuLieLang(langWang) ;
ZhenChaLang zhenChaLang = new ZhenChaLang(langWang) ;
// 狼王下达命令就是发送通知
langWang.xiaDaMingling("1、分工合作,捕猎狼根据侦查狼反馈看机行事 \n" +
"2、侦查狼永远把危险放在第一位,遇到危险第一时间提醒大家撤退");
}
}
观察者模式的优缺点
优点
1、解耦,被观察者只知道观察者列表「抽象接口」,被观察者不知道具体的观察者
2、被观察者发送通知,所有注册的观察者都会收到信息「可以实现广播机制」
缺点
1、如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
2、观察者知道被观察者发送通知了,但是观察者不知道所观察的对象具体是如
何发生变化的
3、如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调
用,会导致系统崩溃
网友评论