情景
- 平时很多人都会用新浪微博, 关注女神动态, 女神就是通知者,也叫主题, 而关注女神的这些人,就是观察者,也叫订阅者, 既然订阅了女神的动态, 如果女神有新的动态, 我们就会想通过某一个渠道被通知, 这种交互方式就是观察者模式
常见的使用场景;
- spring中的event, listener等都是观察者模式
代码实现
/**
* 通知者, 也是主题发布者, 就是为了被观察或者订阅的,
* 主题如果状态发生改变,就会通知所有的订阅者(观察者)
*/
public interface Subject {
void addFans(Observer fans);
void deleteFans(Observer fans);
void notifyFans();
void addFansWithEventListener(Observer fans, String event);
void statusChange();
}
/**
* 屌丝朋友们都爱关注的刘亦菲仙女
*/
public class LiuYiFei implements Subject {
@Override
public void addFans(Observer fans) {
fansWithEventListener.put(fans, null);
}
@Override
public void deleteFans(Observer fans){
fansWithEventListener.remove(fans);
}
/**
* 记录每个对象的回调事件
* 模拟了 c# eventhandler liuyifei.update += zhangsan.getinfobyemail //大话设计模式 14
*/
private Map<Observer, String> fansWithEventListener = new HashMap<>();
/**
* 通知所有的粉丝儿, 面条儿....
*/
@Override
public void notifyFans() {
for (Observer fans : fansWithEventListener.keySet()) {
if(fansWithEventListener.get(fans) == null){
//默认采用qq通知
fans.getInfoByQQ();
}else{
//如果有自己注册的事件, 就采用指定的通知方式通知
try {
fans.getClass().getDeclaredMethod(fansWithEventListener.get(fans)).invoke(fans) ;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public void addFansWithEventListener(Observer fans, String event) {
fansWithEventListener.put(fans, event);
}
/**
* 女神的状态改变, 所有订阅者第一时间收到消息
*/
@Override
public void statusChange() {
this.notifyFans();
}
}
/**
* 事件委托模型: 订阅的时候顺便制定通知的方式
* 基础的观察者模式通知方式比较单一, 只能通过一条路径通知订阅者
* 现在我们有微信, 有扣扣, 有邮箱, 我们需要自己指定通过什么渠道来订阅通知
*/
public interface Observer {
//主题发生改变时的通知渠道
void getInfoByQQ();
//主题发生改变时使用微信通知
void getInfoByWeiXin();
//主题发生改变时使用邮件通知
void getInfoByEMail();
}
public class ZhangSan implements Observer {
@Override
public void getInfoByQQ() {
System.out.println("我是张三, QQ通知: 女神更新状态了!!");
}
@Override
public void getInfoByWeiXin() {
System.out.println("我是张三, 微信通知: 女神更新状态了!!");
}
@Override
public void getInfoByEMail() {
System.out.println("我是张三, 邮箱通知: 女神更新状态了!!");
}
}
public class LiSi implements Observer {
@Override
public void getInfoByQQ() {
System.out.println("我是李四,QQ通知: 女神更新状态了!!");
}
@Override
public void getInfoByWeiXin() {
System.out.println("我是李四,微信通知: 女神更新状态了!!");
}
@Override
public void getInfoByEMail() {
System.out.println("我是李四,邮箱通知: 女神更新状态了!!");
}
}
/**
* 王二麻子实现订阅接口就可以有获取新动态的能力
*/
public class WangerMaZi implements Observer {
/**
* 订阅了菲菲女神微博后, 女神发新状态通知王二麻子的渠道
*/
@Override
public void getInfoByQQ() {
System.out.println("我是王二麻子, QQ通知: 女神更新状态了!!");
}
@Override
public void getInfoByWeiXin() {
System.out.println("我是王二麻子, 微信通知: 女神更新状态了!!");
}
@Override
public void getInfoByEMail() {
System.out.println("我是王二麻子, 邮箱通知: 女神更新状态了!!");
}
}
public class TestEventHandler {
/**
* 女神刘亦菲更新微博状态后发生什么
*/
@Test
public void afterLiuyifeiUpdateWeibo(){
Subject liuyifei = new LiuYiFei();
Observer zhangSan = new ZhangSan();
Observer liSi = new LiSi();
Observer wangerMaZi = new WangerMaZi();
// liuyifei.addListener(zhangSan, "微信通知");
// liuyifei.addListener(lisiSan, "邮箱通知");
//指定通知以后的回调方法
liuyifei.addFansWithEventListener(zhangSan, "getInfoByWeiXin");
liuyifei.addFansWithEventListener(wangerMaZi, "getInfoByEMail");
liuyifei.addFans(liSi);
liuyifei.statusChange();
}
}
源码路径
https://github.com/offline7LY/designpattern/tree/master/observer