Java中利用多态实现观察者模式,核心是定义Observer接口,具体观察者实现update()方法,Subject通过List<Observer>持有抽象引用并统一调用update(),运行时动态绑定不同实现,支持开闭原则与Lambda简化。

Java 中利用多态实现观察者模式,核心在于将观察者(Observer)定义为接口或抽象类,让具体观察者通过继承或实现该类型,从而在被观察者(Subject)通知时,能以统一方式调用不同观察者的更新逻辑——这正是多态的体现:同一方法调用,不同对象执行不同行为。
定义观察者接口,体现多态基础
观察者接口声明统一的响应方法,如 update()。所有具体观察者都实现它,但各自内部逻辑独立:
public interface Observer {
void update(String message); // 统一入口,行为由子类决定
}
比如两个具体观察者:
- EmailObserver 实现后发送邮件
- SmsObserver 实现后发短信
它们类型都是 Observer,但调用 observer.update("订单已创建") 时,实际执行的是各自重写的方法——这就是运行时多态。
立即学习“Java免费学习笔记(深入)”;
被观察者持有观察者列表,只依赖抽象类型
Subject 类不关心观察者具体是谁,只维护 List<Observer>,添加和通知都面向接口:
public class OrderSubject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) {
observers.add(o);
}
public void notifyObservers(String msg) {
for (Observer o : observers) {
o.update(msg); // 多态调用:实际执行各子类的 update
}
}
}
这样新增观察者(如 PushNotificationObserver)无需修改 Subject 代码,符合开闭原则,也凸显多态的价值。
结合 Java 8+ 函数式接口,用 Lambda 简化多态使用
若观察者逻辑简单,可直接用函数式接口替代传统类,进一步简化多态表达:
@FunctionalInterface
public interface Observer {
void update(String message);
}
// 使用时可传入 Lambda,本质仍是多态:不同 lambda 对象响应同一 update 调用
subject.addObserver(msg -> System.out.println("控制台收到:" + msg));
subject.addObserver(msg -> sendWeChat(msg));
每个 Lambda 都生成一个实现了 Observer 的匿名实例,调用 update() 时自动分派到对应逻辑。
注意避免强耦合,确保多态真正生效
常见误区是 Subject 中硬编码具体观察者类型(如 if (o instanceof EmailObserver)),这会破坏多态。正确做法是:
- Subject 只调用
observer.update(...),不做类型判断 - 把差异化逻辑完全下放到具体观察者内部(例如 EmailObserver 自己决定收件人、模板等)
- 必要时可在 update 参数中传递上下文对象(如
update(OrderEvent event)),让观察者按需提取信息
这样扩展新观察者只需新增实现类,不碰原有逻辑,多态才真正发挥作用。


















