定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。
源码地址: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;@Overridepublic List<Observer> getObservers() {return this.observers;}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {int index = observers.indexOf(observer);if (index >= 0) {observers.remove(observer);}}@Overridepublic 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;}@Overridepublic 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
23种设计模式JAVA案例