先上图
观察者模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象,同时监听某一个主题对象。这个主题对象状态发生改变的时候,会通知所有得观察者对象,使得它们可以自动更新自己。
上面的定义是抽象的,对于很多同学而言第一次看到这种很官方的定义都感觉有点蒙蔽。当然咱们今天的这篇文章就是将抽象的定义用实实在在的代码将其实现,里面穿插着一些小故事。
进入故事先来看看我们故事的主人公吧。
1.静香 (美女)
2.大雄 (痴汉)
3.胖虎 (痴汉)
众所周知,痴汉和美女之间的关系,不就是那种咳咳~~关系吗?你说对吧,痴汉总是一直偷偷观察着美女对吧,每当美女要去洗个澡啥的,痴汉们总是不约而至。咦,仔细想想这不就是咱们的观察模式吗?每当美女的状态改变, 她的观察者们就可以做出一些反应的动作。
好嘞,上面的分析很符合今天要讨论的观察者设计模式。那么话不多说,看看代码怎么实现痴汉和美女之间的爱恨纠缠吧。
BeautifulGirl(接口)package com.zxy.basic;
/**
* @program: basic
* @author: Josiah
* @create: 2020-04-03 11:55
**/
public interface BeautifulGirl {
/**
* 注册观察者
* @param observer
*/
void addObserver(Satyr observer);
/**
* 移除观察者
* @param observer
*/
void removerObserver(Satyr observer);
/**
* 通知所有得观察者
*/
void notifyObservers();
}
Satyr (痴汉接口 )
package com.zxy.basic;
/**
* @program: basic
* @author: Josiah
* @create: 2020-04-03 11:50
**/
public interface Satyr {
/**
* 搞事情
* @param msg
*/
void update(String msg);
}
上面已经定义了美女和痴汉的接口,那么总有具体的美女和痴汉们吧。那么下面就是咱们的胖虎,大雄,静香登上舞台。
静香类 package com.zxy.basic;
import java.util.ArrayList;
import java.util.List;
/**
* @program: basic
* @author: Josiah
* @create: 2020-04-03 12:00
**/
public class JingXiang implements BeautifulGirl {
//偷偷关注静香的痴汉们
private final List satyrList = new ArrayList();
private String msg;
@Override
public void addObserver(Satyr observer) {
satyrList.add(observer);
}
@Override
public void removerObserver(Satyr observer) {
int index = satyrList.indexOf(observer);
if(index>=0){
satyrList.remove(index);
}
}
@Override
public void notifyObservers() {
for (Satyr satyr : satyrList) {
satyr.update(msg);
}
}
/**
* 静香得一举一动,都会不胫而走
* @param msg
*/
public void life(String msg){
this.msg = msg;
notifyObservers();
}
}
大雄类
package com.zxy.basic;
/**
* 大雄
* @program: basic
* @author: Josiah
* @create: 2020-04-03 12:07
**/
public class DaXiong implements Satyr {
private BeautifulGirl beautifulGirl;
public DaXiong(BeautifulGirl beautifulGirl) {
this.beautifulGirl = beautifulGirl;
//大雄偷偷得关注了静香
beautifulGirl.addObserver(this);
}
@Override
public void update(String msg) {
if(msg.equals("TakeShower")){
System.out.println("DaXiong:哇,有点上头了。。我要去偷看!");
}else if(msg.equals("Study")){
System.out.println("DaXiong:太困了,睡觉去吧..");
}
}
}
胖虎类
package com.zxy.basic;
/**
* 胖虎
* @program: basic
* @author: Josiah
* @create: 2020-04-03 12:07
**/
public class PangHu implements Satyr {
private BeautifulGirl beautifulGirl;
public PangHu(BeautifulGirl beautifulGirl) {
this.beautifulGirl = beautifulGirl;
//胖虎偷偷得关注了静香
beautifulGirl.addObserver(this);
}
@Override
public void update(String msg) {
if(msg.equals("TakeShower")){
System.out.println("Panghu:我可是堂堂虎大将军,岂能有非分之想?");
}else if(msg.equals("Study")){
System.out.println("Panghu:I love Study");
}
}
}
那么接下来就是看看静香的一举一动被大雄和胖虎监控着吗?再看看大雄和胖虎的各种反应吧!
测试类package com.zxy.basic.lambda;
import com.zxy.basic.DaXiong;
import com.zxy.basic.JingXiang;
import com.zxy.basic.PangHu;
import java.io.IOException;
/**
* @program: basic
* @author: Josiah
* @create: 2020-04-03 12:12
**/
public class ObserverTest {
public static void main(String[] args) throws IOException {
JingXiang jingXiang = new JingXiang();
PangHu pangHu = new PangHu(jingXiang);
DaXiong daXiong = new DaXiong(jingXiang);
jingXiang.life("TakeShower");
jingXiang.life("Study");
System.out.println("=================");
//静香发现了大雄偷窥她,将他删除掉
jingXiang.removerObserver(daXiong);
jingXiang.life("TakeShower");
jingXiang.life("Study");
}
}
运行结果:
观察者模式的主要解决的问题是:一个对象状态再改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优点: 1.观察者和被观察者是抽象耦合的。2.建立了一套触发机制。
缺点: 1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
最后再看看结构图: