定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。
源码地址:https://gitee.com/yang-kairui/design-pattern
JAVA的JDK和很多框架都用到了观察者模式,最典型的比如说spring mvc中的DispatcherServelet以及Zookeeper的动态监控注册中心,感兴趣的话可以去阅读一下源码
如上图所示,服务号就是我们的主题,使用者就是观察者。现在我们明确下功能:
1、服务号就是主题,业务就是推送消息
2、观察者只需要订阅主题,只要有新的消息就会送来
3、当不想要此主题消息时,取消订阅
4、只要服务号还在,就会一直有人订阅
好了,现在我们来看看观察者模式的类图:
接下来就是代码时间了,我们模拟一个买彩票的场景,彩票站就是主题,买彩票的人就是观察者。
首先定义两个接口,主题接口Subject、订阅者接口Observer
/**
* 所有的被观察主题需要实现该接口
*
* @author ykr
* @date 2022/3/31
*/
public interface Subject {
/**
* 存储所有观察者
* @return List<Observer>
*/
List<Observer> getObservers();
/**
* 注册一个观察者
* @param observer 订阅的观察者对象
*/
void registerObserver(Observer observer);
/**
* 移除一个观察者
* @param observer 订阅的观察者对象
*/
void removeObserver(Observer observer);
/**
* 通知所有观察者
*/
void notifyObservers();
}
/**
* 所有订阅者需要实现该接口
*
* @author ykr
* @date 2022/3/31
*/
public interface Observer {
void update(String msg);
}
接下来实现一个彩票主题LotterySubject 和彩民订阅者LotteryHolders
/**
* 彩票主题
*
* @author ykr
* @date 2022/3/31
*/
public class LotterySubject implements Subject {
/**
* 所有买彩票的彩民
*/
private List<Observer> observers = new ArrayList<>();
/**
* 开奖号码
*/
private String msg;
@Override
public List<Observer> getObservers() {
return this.observers;
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int index = observers.indexOf(observer);
if (index >= 0) {
observers.remove(observer);
}
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(msg);
}
}
/**
* 开奖
*/
public void lottery(String msg) {
this.msg = msg;
notifyObservers();
}
}
/**
* 持有彩票的人
*
* @author ykr
* @date 2022/3/31
*/
public class LotteryHolders implements Observer {
private String lottery;
LotteryHolders(String lottery) {
this.lottery = lottery;
}
@Override
public void update(String msg) {
//开奖
System.out.println("本期开奖号码:" + msg + ",我的号码:" + lottery);
}
}
最后模拟买彩票案例LotteryTest
/**
* 买彩票模拟
*
* @author ykr
* @date 2022/3/31
*/
public class LotteryTest {
public static void main(String[] args) {
LotteryHolders li = new LotteryHolders(String.valueOf(new Random().nextInt(10)));
LotteryHolders wang = new LotteryHolders(String.valueOf(new Random().nextInt(10)));
LotteryHolders yang = new LotteryHolders(String.valueOf(new Random().nextInt(10)));
LotterySubject lotteryStore = new LotterySubject();
lotteryStore.registerObserver(li);
lotteryStore.registerObserver(wang);
lotteryStore.registerObserver(yang);
lotteryStore.lottery("5");
}
}
执行结果
本期开奖号码:5,我的号码:4 本期开奖号码:5,我的号码:9 本期开奖号码:5,我的号码:7