本文参考:
入门对比:Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)_Chen4852010的博客-CSDN博客
一、回调函数
理解了回调函数,也就能更好地理解观察者模式,其很好地利用了回调机制。
回调函数被外部定义实现,由调用方触发,理解为“回头调用定义的函数”。
这里分为两个对象:
- 调用方
- 定义方(面向接口编程,以此规范回调函数的定义)。
回调函数Demo:
-
定义回调接口
/** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public interface ICallBack { void callBack(); }
-
回调触发者动作
/** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public class Caller { public void callerFunc(ICallBack f){ // 这里能传入回调定义方的逻辑 System.out.println("start..."); // 回调函数 f.callBack(); System.out.println("end..."); } }
-
测试
import org.junit.Test; /** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public class TestCallerFunc { @Test public void testCallerFunc(){ Caller caller = new Caller(); caller.callerFunc(new ICallBack() { // 调用方触发定义方的逻辑 @Override public void callBack() { System.out.println("我是自定义的回调函数..."); } }); } }
输出:
start... 我是自定义的回调函数... end...
其实我们最常见的实现Runnable接口创建线程的方式也是回调函数的实现:Runable接口是回调接口,Thread是调用方触发者
@Test
public void testThread(){
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是自定义的回调函数...");
}
}).start();
}
二、观察者模式(发布订阅模式)
观察者模式 (Observer Pattern)是用于建立一种对象和对象之间依赖关系的 对象行为型设计模式 ,其定义为:
在对象之间定义一对多的依赖,当一个对象状态改变时,所有依赖的对象都会自动收到通知。
同样分为两个对象:
-
观察者(Observer)监听被观察者产生的改变。A用户观察B,则A观察者,B是被观察者。观察者对象不知道其他观察者的存在, 它只知道如何更新自己。
-
主题对象(被观察者)内部维护了一个观察者列表,并在消息message产生变化时通知notify()所有的观察者,也就是回调观察者列表中每个observer的回调方法,表示观察者做出反应react()(观察者暴露给被主题对象的)。
观察者模式Demo:
-
定义主题接口
/** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public interface Subject { // 注册观察者 void registerObserver(Observer observer); // 移除观察者 void removeObserver(Observer observer); // 发布一个消息 void publishMessage(String message); // 核心功能,通知观察者 void notifyObservers(); }
-
具体的主题接口实现类
import java.util.ArrayList; import java.util.List; /** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public class ConcreteSubject implements Subject{ // 观察者的列表 private List<Observer> observerList=new ArrayList<>(); // 发布的信息 private String message; @Override public void registerObserver(Observer observer) { observerList.add(observer); } @Override public void removeObserver(Observer observer) { observerList.remove(observer); } @Override public void publishMessage(String message) { this.message=message; // 通知所有观察者 notifyObservers(); } @Override public void notifyObservers() { for(Observer observer:observerList){ // 回调观察者的反应接口 observer.react(message); } } }
-
定义观察者接口
/** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public interface Observer { void react(String message); }
-
具体的观察者接口实现类
/** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public class ConcreteObserver implements Observer{ String name; String recvMeesage; public ConcreteObserver(String name){ this.name=name; } @Override public void react(String message) { this.recvMeesage=message; System.out.println("["+name+"]"+" receive message: "+recvMeesage); } }
-
测试
import org.junit.Test; /** * @Author jiangxuzhao * @Description * @Date 2023/5/21 */ public class TestObserver { @Test public void testObserver(){ // 创建具体主题对象 ConcreteSubject concreteSubject = new ConcreteSubject(); // 创建具体观察者 ConcreteObserver observer1 = new ConcreteObserver("Observer1"); ConcreteObserver observer2 = new ConcreteObserver("Observer2"); // 注册观察者到主题对象 concreteSubject.registerObserver(observer1); concreteSubject.registerObserver(observer2); // 发布消息Message concreteSubject.publishMessage("观察者模式测试消息..."); // 再提醒一次 concreteSubject.notifyObservers(); // 移除一个观察者并通知当前新的观察者列表 concreteSubject.removeObserver(observer1); concreteSubject.notifyObservers(); } }
输出:
[Observer1] receive message: 观察者模式测试消息... [Observer2] receive message: 观察者模式测试消息... // publishMessage提醒一次 [Observer1] receive message: 观察者模式测试消息... [Observer2] receive message: 观察者模式测试消息... // 再提醒一次 [Observer2] receive message: 观察者模式测试消息... // 移除了observer1
在JDK和Spring中也有对此模式的实践,参考Java中的设计模式(一):观察者模式-阿里云开发者社区 (aliyun.com)