观察者模式的核心思想特别像现实中的订阅机制。举个例子,你关注了一个网红博主的微博,博主每次发新动态,平台会自动推送给所有粉丝,而你不需要整天手动去刷主页。在编程世界里,这种模式让对象之间建立一种"一对多"的依赖关系:当一个核心对象(称为"主题"或"被观察者")状态变化时,所有依赖它的对象(称为"观察者")会自动收到通知并执行相应操作。这种设计完美解耦了主题和观察者------主题根本不用关心谁在监听它,只管发通知;观察者也只需注册一次,就能长期接收更新。
在Java中实现观察者模式,通常需要四个关键角色。首先是Subject(主题),它定义添加、删除和通知观察者的方法,并维护一个观察者列表。其次是Observer(观察者接口),一般只声明一个update()方法,用于接收主题的通知。接着是ConcreteSubject(具体主题),它继承Subject类,内部维护实际状态数据,当状态改变时调用通知方法遍历观察者列表。最后是ConcreteObserver(具体观察者),实现Observer接口,在update()方法中定义自己的业务逻辑,比如刷新界面或保存日志。
来看个实际代码场景:假设我们在做一个简单的天气预报系统。气象站作为主题,当温度变化时,要自动通知手机APP和户外显示屏这两个观察者。先定义Observer接口:
接着是Subject抽象类,管理观察者集合:
具体主题WeatherStation继承Subject,内部封装温度属性:
两个具体观察者分别实现不同响应逻辑。手机APP观察者:
户外显示屏观察者:
最后在客户端代码中组装整个流程:
运行后会同时输出两条信息,证明两个观察者都收到了通知。如果想新增一个电视终端观察者,只需新建类实现Observer接口并注册到主题,完全不用修改气象站的核心代码。
这种模式的优点很明显。第一是解耦,主题和观察者之间通过接口交互,彼此独立变化。第二是扩展性强,新增观察者无需改动主题代码,符合开闭原则。第三支持广播通信,一次状态更新能触发多个对象响应。但也要注意潜在问题:如果观察者处理太耗时,可能会阻塞主题线程;另外过多的观察者会占用内存,需要合理管理注册与销毁。
实际开发中,观察者模式的应用场景非常广泛。比如Spring框架的事件监听机制,用户注册成功后发布事件,邮件服务和积分服务自动执行;再如Swing GUI中的按钮点击监听,或者消息中间件的发布-订阅模型。Java标准库甚至提供了现成的java.util.Observable类和Observer接口(不过由于设计局限,在Java 9后被标记为过时,更推荐自定义实现)。
说到底,观察者模式把那种"牵一发而动全身"的复杂依赖,变成了清晰可控的订阅关系。下次当你遇到多个对象需要同步状态的场景时,不妨试试这种模式------它能让你的代码像精密的齿轮组一样,一环扣一环地自动运转起来。