设计模式系列文章(基础篇第30篇):观察者模式——对象联动通知,解耦依赖关系
2026/6/19 23:02:03 网站建设 项目流程

大家好,欢迎来到设计模式系列文章(基础篇)的第三十篇内容。在上一篇中,我们学习了行为型模式的第十九种常用模式——迭代器模式,其核心是分离聚合对象与遍历逻辑,提供统一的遍历接口,实现遍历与聚合的解耦,广泛应用于集合遍历、自定义容器等场景。今天,我们将学习行为型模式的第二十种常用模式——观察者模式,它的核心是定义对象间的一对多依赖关系,当一个对象(被观察者)的状态发生变化时,所有依赖它的对象(观察者)都会得到通知并自动更新,实现对象间的联动通知,同时解耦被观察者与观察者的依赖关系。
在日常开发和生活中,观察者模式的应用无处不在。比如我们关注的微信公众号,公众号(被观察者)发布新文章时,所有关注该公众号的用户(观察者)都会收到推送通知,用户无需主动查询,就能及时获取最新内容;再比如电商系统中的订单状态变更,当订单状态从“待付款”变为“已付款”时,库存系统(观察者)会自动扣减库存,物流系统(观察者)会自动创建物流单,消息系统(观察者)会向用户发送支付成功通知;还有生活中的天气预报,气象站(被观察者)监测到天气变化后,会向所有订阅了天气预报的设备(观察者)推送最新天气信息。
这些场景的核心需求是“对象状态变化时,联动通知所有依赖对象并触发更新”,若直接让被观察者与每个观察者建立直接依赖,会导致两者耦合过高——当新增、删除观察者时,需要修改被观察者的代码,违背开闭原则;同时,被观察者需要知道所有观察者的存在,增加了系统的维护成本。观察者模式则通过引入“抽象被观察者”和“抽象观察者”,将被观察者与观察者解耦,被观察者只需通知抽象观察者,无需关心具体观察者的实现;观察者只需实现抽象观察者接口,无需关心被观察者的具体逻辑,大幅提升了系统的灵活性和可扩展性。今天,我们就从核心定义、结构、实战实现、场景对比、避坑指南全维度讲解,帮大家彻底掌握这种“对象联动通知”的实用设计模式。

一、观察者模式的核心定义与设计初衷

1. 核心定义
观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。观察者模式又称发布-订阅模式(Publish/Subscribe Pattern),核心是解耦被观察者与观察者,实现状态变化的联动通知,确保观察者与被观察者各自独立扩展。
通俗理解:观察者模式就像我们生活中的“订阅报纸”,报社(被观察者)负责发布报纸,订阅报纸的读者(观察者)会定期收到报纸,读者无需关心报社的报纸制作、发行流程,只需订阅即可;当报社发布新报纸(状态变化)时,所有订阅的读者都会收到通知并获取报纸;读者可以随时订阅、取消订阅,报社无需修改自身逻辑,只需维护订阅列表即可。再比如班级群通知,老师(被观察者)在群里发送通知(状态变化),所有进群的学生(观察者)都会收到通知,学生可以随时进群、退群,老师无需关心具体有多少学生,只需发送通知即可。

2. 设计初衷(解决的核心问题)
观察者模式的出现,核心是解决“对象间存在一对多依赖、状态变化需要联动通知,且耦合度高”的痛点,具体解决3个核心问题:

  • 解耦依赖关系:被观察者无需知道具体观察者的实现,只需依赖抽象观察者;观察者无需知道被观察者的具体逻辑,只需依赖抽象被观察者,实现两者的解耦;
  • 实现联动通知:当被观察者的状态发生变化时,自动通知所有注册的观察者,触发观察者的更新操作,无需手动调用,实现状态联动;
  • 灵活扩展:新增、删除观察者时,无需修改被观察者的代码,只需新增、删除观察者对象并注册到被观察者,符合开闭原则;被观察者和观察者可独立扩展自身逻辑,互不影响。

3. 设计原则适配
观察者模式严格贴合面向对象设计核心原则,尤其在“开闭原则”和“依赖倒转原则”上表现突出,是实现对象联动通知的最佳实践:

  • 开闭原则:新增观察者或被观察者时,无需修改原有代码,只需新增对应的类并实现抽象接口,扩展性强;
  • 依赖倒转原则:被观察者依赖抽象观察者,不依赖具体观察者;观察者依赖抽象被观察者,不依赖具体被观察者,降低了耦合度;
  • 单一职责原则:被观察者只负责维护自身状态和通知观察者,观察者只负责接收通知并执行自身的更新逻辑,各司其职;
  • 迪米特法则(最少知道原则):被观察者只需知道抽象观察者的接口,无需知道具体观察者的内部实现;观察者只需知道抽象被观察者的接口,无需知道被观察者的内部状态和实现逻辑。

二、观察者模式的核心结构(4个核心角色)

观察者模式的结构围绕“被观察者状态变化、通知观察者更新”展开,核心包含4个角色,各司其职、协同完成对象间的联动通知,我们以“微信公众号推送”为场景,逐一拆解角色职责与交互逻辑:

1. 抽象被观察者(Subject)
所有具体被观察者的抽象父类或接口,定义了管理观察者的核心方法(注册观察者、删除观察者)和通知观察者的方法。抽象被观察者维护一个观察者列表,负责注册、删除观察者,并在自身状态变化时,通知所有注册的观察者。对应微信公众号场景中的“抽象公众号”,定义注册订阅者、删除订阅者、推送通知的接口。

2. 具体被观察者(Concrete Subject)
实现抽象被观察者接口,维护自身的状态,当自身状态发生变化时,调用通知方法,向所有注册的观察者发送通知。具体被观察者是状态变化的触发者,负责维护观察者列表,并在状态变化时触发联动通知。对应微信公众号场景中的“具体微信公众号”,维护公众号的文章状态,当发布新文章(状态变化)时,向所有订阅者推送通知。

3. 抽象观察者(Observer)
所有具体观察者的抽象父类或接口,定义了观察者接收通知并执行更新操作的方法。抽象观察者规范了观察者的核心行为,确保所有具体观察者都能响应被观察者的通知。对应微信公众号场景中的“抽象订阅者”,定义接收公众号推送通知的接口。

4. 具体观察者(Concrete Observer)
实现抽象观察者接口,是依赖于被观察者的对象,当接收到被观察者的通知时,执行自身的更新操作(如接收推送、处理业务逻辑)。具体观察者不关心被观察者的状态变化细节,只需在收到通知后,执行自身的业务逻辑。对应微信公众号场景中的“具体订阅者”,接收公众号的推送通知,并显示文章内容。
核心关系总结:抽象被观察者定义观察者管理和通知规范,具体被观察者实现状态管理和通知逻辑;抽象观察者定义接收通知和更新的规范,具体观察者实现更新逻辑。具体被观察者维护观察者列表,注册、删除具体观察者;当具体被观察者状态变化时,调用通知方法,触发所有注册的具体观察者执行更新操作;被观察者与观察者通过抽象接口解耦,可独立扩展。

三、观察者模式的核心逻辑与执行流程

观察者模式的核心逻辑是“一对多依赖、状态联动通知、解耦依赖关系”,标准执行流程分为六步,全程实现被观察者与观察者的解耦,逻辑闭环,我们以“微信公众号推送新文章”为例,拆解执行流程:

  1. 定义抽象观察者接口:声明接收通知并执行更新操作的方法;
  2. 定义抽象被观察者接口:声明注册观察者、删除观察者、通知观察者的方法;
  3. 实现具体被观察者:维护自身状态和观察者列表,实现注册、删除观察者的方法,在状态变化时调用通知方法;
  4. 实现具体观察者:实现抽象观察者的更新方法,接收被观察者的通知并执行自身逻辑;
  5. 注册观察者:创建具体被观察者和具体观察者,将具体观察者注册到具体被观察者的观察者列表中;
  6. 触发通知:具体被观察者的状态发生变化,调用通知方法,向所有注册的具体观察者发送通知,具体观察者接收通知并执行更新操作。
    关键要点:具体被观察者只负责维护观察者列表和通知观察者,不关心观察者的具体更新逻辑;具体观察者只负责接收通知并执行自身更新逻辑,不关心被观察者的状态变化细节;新增观察者时,只需创建具体观察者并注册到被观察者,无需修改被观察者代码;被观察者与观察者通过抽象接口解耦,确保两者可独立扩展。

四、观察者模式的实战实现(微信公众号推送场景)

我们以高频的微信公众号推送为场景,使用Java代码实现观察者模式,微信公众号(具体被观察者)支持订阅、取消订阅、推送新文章;订阅者(具体观察者)支持接收公众号推送的文章通知并查看;新增订阅者(如手机用户、电脑用户)时,无需修改公众号代码,直观体现观察者模式“联动通知、解耦依赖”的核心优势。
场景说明:微信公众号(具体被观察者)维护订阅者列表,支持订阅者订阅、取消订阅;当公众号发布新文章(状态变化)时,自动向所有订阅者推送文章通知;订阅者(具体观察者)分为手机用户和电脑用户,手机用户接收推送后显示文章摘要,电脑用户接收推送后显示完整文章;新增订阅者类型(如平板用户)时,只需新增对应的具体观察者类,无需修改公众号代码。

1. 第一步:定义抽象观察者接口(Observer)

// 抽象观察者:抽象订阅者,定义接收通知的方法 public interface Observer{// 接收被观察者的通知(此处为接收公众号推送的文章) void update(String articleTitle, String articleContent);}

2. 第二步:定义抽象被观察者接口(Subject)

// 抽象被观察者:抽象公众号,定义管理订阅者和推送通知的方法 public interface Subject{// 注册订阅者(添加观察者) void registerObserver(Observer observer);// 删除订阅者(移除观察者) void removeObserver(Observer observer);// 推送通知(通知所有订阅者) void notifyObservers(String articleTitle, String articleContent);}

3. 第三步:实现具体观察者类(Concrete Observer)

(1)手机用户订阅者

// 具体观察者:手机用户订阅者,接收公众号推送并显示文章摘要 public class MobileUser implements Observer{// 订阅者用户名 private String username;// 构造方法:初始化用户名 public MobileUser(String username){this.username=username;}// 接收通知,显示文章摘要(手机端适配) @Override public void update(String articleTitle, String articleContent){System.out.println("【手机用户-"+ username +"】收到公众号推送:");System.out.println("文章标题:"+ articleTitle);System.out.println("文章摘要:"+ articleContent.substring(0,50)+"...");System.out.println("--------------------------");}// getter方法(供被观察者管理) public StringgetUsername(){returnusername;}}

(2)电脑用户订阅者

// 具体观察者:电脑用户订阅者,接收公众号推送并显示完整文章 public class ComputerUser implements Observer{// 订阅者用户名 private String username;// 构造方法:初始化用户名 public ComputerUser(String username){this.username=username;}// 接收通知,显示完整文章(电脑端适配) @Override public void update(String articleTitle, String articleContent){System.out.println("【电脑用户-"+ username +"】收到公众号推送:");System.out.println("文章标题:"+ articleTitle);System.out.println("完整文章:"+ articleContent);System.out.println("--------------------------");}// getter方法(供被观察者管理) public StringgetUsername(){returnusername;}}

4. 第四步:实现具体被观察者类(Concrete Subject)

// 具体被观察者:微信公众号,实现订阅管理和推送通知的方法importjava.util.ArrayList;importjava.util.List;public class WeChatOfficialAccount implements Subject{// 公众号名称 private String accountName;// 维护订阅者列表(观察者列表) private List<Observer>observerList=new ArrayList<>();// 构造方法:初始化公众号名称 public WeChatOfficialAccount(String accountName){this.accountName=accountName;}// 注册订阅者(添加观察者到列表) @Override public void registerObserver(Observer observer){if(observer!=null&&!observerList.contains(observer)){observerList.add(observer);String username="";if(observer instanceof MobileUser){username=((MobileUser)observer).getUsername();} else if(observer instanceof ComputerUser){ username=((ComputerUser)observer).getUsername();} System.out.println("订阅者【"+username+"】已订阅公众号【"+accountName+"】");} }//删除订阅者(从列表中移除观察者) @Override public void removeObserver(Observer observer){ if(observer!=null&&observerList.contains(observer)){observerList.remove(observer);String username="";if(observer instanceof MobileUser){username=((MobileUser)observer).getUsername();}elseif(observer instanceof ComputerUser){username=((ComputerUser)observer).getUsername();}System.out.println("订阅者【"+ username +"】已取消订阅公众号【"+ accountName +"】");}else{System.out.println("该订阅者未订阅此公众号,取消订阅失败");}}// 推送通知:向所有订阅者发送文章推送 @Override public void notifyObservers(String articleTitle, String articleContent){System.out.println("\n公众号【"+ accountName +"】发布新文章,开始推送通知...");// 遍历所有订阅者,触发更新操作for(Observer observer:observerList){observer.update(articleTitle, articleContent);}}// 辅助方法:发布新文章(触发状态变化,调用通知方法) public void publishArticle(String articleTitle, String articleContent){System.out.println("\n公众号【"+ accountName +"】发布新文章:"+ articleTitle);// 状态变化,通知所有订阅者 notifyObservers(articleTitle, articleContent);}}

5. 第五步:客户端测试

// 客户端测试:微信公众号推送场景 public class ObserverPatternTest{public static void main(String[]args){//1. 创建具体被观察者(微信公众号) Subject officialAccount=new WeChatOfficialAccount("设计模式学习指南");//2. 创建具体观察者(订阅者) Observer mobileUser1=new MobileUser("张三");Observer mobileUser2=new MobileUser("李四");Observer computerUser1=new ComputerUser("王五");Observer computerUser2=new ComputerUser("赵六");//3. 订阅公众号(注册观察者) officialAccount.registerObserver(mobileUser1);officialAccount.registerObserver(mobileUser2);officialAccount.registerObserver(computerUser1);officialAccount.registerObserver(computerUser2);//4. 测试1:公众号发布第一篇文章,推送通知 String article1Title="观察者模式核心讲解";String article1Content="观察者模式又称发布-订阅模式,核心是定义对象间的一对多依赖关系,当被观察者状态变化时,自动通知所有观察者并触发更新...(此处省略1000字)";((WeChatOfficialAccount)officialAccount).publishArticle(article1Title, article1Content);//5. 测试2:取消订阅(删除观察者) officialAccount.removeObserver(mobileUser2);System.out.println();//6. 测试3:公众号发布第二篇文章,推送通知(取消订阅的用户不再收到) String article2Title="观察者模式实战案例解析";String article2Content="本文以微信公众号推送为场景,详细讲解观察者模式的实战实现,包括抽象被观察者、具体被观察者、抽象观察者、具体观察者的代码实现...(此处省略800字)";((WeChatOfficialAccount)officialAccount).publishArticle(article2Title, article2Content);//7. 测试4:新增订阅者类型(平板用户,无需修改公众号代码) System.out.println("\n=== 新增平板用户订阅者 ===");Observer padUser=new PadUser("孙七");officialAccount.registerObserver(padUser);((WeChatOfficialAccount)officialAccount).publishArticle("观察者模式避坑指南","本文总结了观察者模式的5个常见坑及避坑指南,帮助大家在实际开发中规避问题...(此处省略600字)");}// 新增具体观察者:平板用户(无需修改公众号代码,体现扩展性) static class PadUser implements Observer{private String username;public PadUser(String username){this.username=username;}@Override public void update(String articleTitle, String articleContent){System.out.println("【平板用户-"+ username +"】收到公众号推送:");System.out.println("文章标题:"+ articleTitle);System.out.println("适配平板的文章内容:"+ articleContent.substring(0,80)+"...(点击查看完整内容)");System.out.println("--------------------------");}public StringgetUsername(){returnusername;}}}

运行结果

订阅者【张三】已订阅公众号【设计模式学习指南】 订阅者【李四】已订阅公众号【设计模式学习指南】 订阅者【王五】已订阅公众号【设计模式学习指南】 订阅者【赵六】已订阅公众号【设计模式学习指南】 公众号【设计模式学习指南】发布新文章:观察者模式核心讲解 公众号【设计模式学习指南】发布新文章,开始推送通知... 【手机用户-张三】收到公众号推送: 文章标题:观察者模式核心讲解 文章摘要:观察者模式又称发布-订阅模式,核心是定义对象间的一对多依赖关系,当被观察者状态变化时... -------------------------- 【手机用户-李四】收到公众号推送: 文章标题:观察者模式核心讲解 文章摘要:观察者模式又称发布-订阅模式,核心是定义对象间的一对多依赖关系,当被观察者状态变化时... -------------------------- 【电脑用户-王五】收到公众号推送: 文章标题:观察者模式核心讲解 完整文章:观察者模式又称发布-订阅模式,核心是定义对象间的一对多依赖关系,当被观察者状态变化时,自动通知所有观察者并触发更新...(此处省略1000字) -------------------------- 【电脑用户-赵六】收到公众号推送: 文章标题:观察者模式核心讲解 完整文章:观察者模式又称发布-订阅模式,核心是定义对象间的一对多依赖关系,当被观察者状态变化时,自动通知所有观察者并触发更新...(此处省略1000字) -------------------------- 订阅者【李四】已取消订阅公众号【设计模式学习指南】 公众号【设计模式学习指南】发布新文章:观察者模式实战案例解析 公众号【设计模式学习指南】发布新文章,开始推送通知... 【手机用户-张三】收到公众号推送: 文章标题:观察者模式实战案例解析 文章摘要:本文以微信公众号推送为场景,详细讲解观察者模式的实战实现,包括抽象被观察者、具体被观察者、抽象观察者、具体观察者的代码实现... -------------------------- 【电脑用户-王五】收到公众号推送: 文章标题:观察者模式实战案例解析 完整文章:本文以微信公众号推送为场景,详细讲解观察者模式的实战实现,包括抽象被观察者、具体被观察者、抽象观察者、具体观察者的代码实现...(此处省略800字) -------------------------- 【电脑用户-赵六】收到公众号推送: 文章标题:观察者模式实战案例解析 完整文章:本文以微信公众号推送为场景,详细讲解观察者模式的实战实现,包括抽象被观察者、具体被观察者、抽象观察者、具体观察者的代码实现...(此处省略800字) --------------------------===新增平板用户订阅者===订阅者【孙七】已订阅公众号【设计模式学习指南】 公众号【设计模式学习指南】发布新文章:观察者模式避坑指南 公众号【设计模式学习指南】发布新文章,开始推送通知... 【手机用户-张三】收到公众号推送: 文章标题:观察者模式避坑指南 文章摘要:本文总结了观察者模式的5个常见坑及避坑指南,帮助大家在实际开发中规避问题... -------------------------- 【电脑用户-王五】收到公众号推送: 文章标题:观察者模式避坑指南 完整文章:本文总结了观察者模式的5个常见坑及避坑指南,帮助大家在实际开发中规避问题...(此处省略600字) -------------------------- 【电脑用户-赵六】收到公众号推送: 文章标题:观察者模式避坑指南 完整文章:本文总结了观察者模式的5个常见坑及避坑指南,帮助大家在实际开发中规避问题...(此处省略600字) -------------------------- 【平板用户-孙七】收到公众号推送: 文章标题:观察者模式避坑指南 适配平板的文章内容:本文总结了观察者模式的5个常见坑及避坑指南,帮助大家在实际开发中规避问题...(点击查看完整内容) --------------------------

从运行结果可以看出,观察者模式成功实现了微信公众号的推送功能:公众号(具体被观察者)维护订阅者列表,支持订阅、取消订阅,发布新文章时自动通知所有订阅者;不同类型的订阅者(手机用户、电脑用户、平板用户)接收通知后,执行各自的更新逻辑,无需修改公众号代码;新增平板用户订阅者时,只需新增具体观察者类,体现了良好的扩展性。同时,公众号与订阅者通过抽象接口解耦,公众号无需知道订阅者的具体类型和实现逻辑,订阅者也无需知道公众号的内部实现,完美符合开闭原则和依赖倒转原则;取消订阅的用户不再收到推送,确保了通知的准确性和灵活性。

五、观察者模式的高频应用场景

观察者模式适用于所有存在一对多依赖关系、需要在被观察者状态变化时联动通知观察者的业务场景,核心作用是实现对象间的联动通知和解耦,以下是四大高频落地场景:

1. 消息通知系统(最经典应用)
各类消息通知场景中,被观察者状态变化时,需要通知所有依赖的观察者,是观察者模式最核心的应用场景:

  • 公众号/订阅号推送:如实战场景中的微信公众号,发布新内容时通知所有订阅者;
  • 邮件/短信通知:系统触发特定事件(如订单支付、账号登录)时,向用户发送邮件、短信通知;
  • 消息队列通知:消息生产者(被观察者)发送消息到队列,所有消息消费者(观察者)接收消息并处理。

2. 事件驱动系统
事件驱动系统中,事件源(被观察者)触发事件后,所有监听该事件的监听器(观察者)都会收到通知并执行相应逻辑:

  • UI事件处理:前端页面中,按钮点击(事件源)触发事件,所有监听该按钮的监听器(观察者)执行逻辑(如弹窗、跳转);
  • 系统事件监听:后端系统中,监听服务启动、配置变更等事件,事件触发时执行初始化、更新逻辑;
  • Spring事件机制:Spring的ApplicationEvent(事件源)和ApplicationListener(监听器),本质是观察者模式,实现系统内部的事件联动。

3. 业务系统联动场景
复杂业务系统中,多个模块之间存在联动关系,一个模块的状态变化需要触发其他模块的更新:

  • 电商订单联动:订单状态(被观察者)变化时,通知库存模块(扣减库存)、物流模块(创建物流单)、积分模块(增加积分);
  • 库存管理联动:库存数量(被观察者)低于阈值时,通知采购模块(触发采购)、预警模块(发送预警通知);
  • 用户状态联动:用户账号状态(被观察者)变为“禁用”时,通知所有关联模块(禁用用户权限、停止服务)。

4. 框架底层与工具类设计
主流开源框架和工具类中,大量使用观察者模式实现事件联动和通知机制,提升框架的灵活性:

  • Spring框架:Spring的事件机制(ApplicationEvent、ApplicationListener),实现Bean之间的事件联动;
  • Java Swing:Swing的事件监听机制(如ActionListener、MouseListener),本质是观察者模式;
  • RxJava/RxAndroid:基于响应式编程,核心是观察者模式,实现数据流的联动通知和处理。

六、观察者模式 vs 迭代器模式(重点区分)

观察者模式与上一篇学习的迭代器模式,都属于行为型模式,且都涉及“对象间的交互与解耦”,但核心目标、使用场景、核心逻辑完全不同,极易混淆,通过表格清晰对比,帮大家彻底区分:

对比维度观察者模式迭代器模式
核心目标定义一对多依赖,实现被观察者状态变化时的联动通知,解耦依赖关系分离聚合与遍历逻辑,提供统一遍历接口,实现遍历解耦
核心逻辑被观察者维护观察者列表,状态变化时通知所有观察者,观察者执行更新迭代器封装遍历逻辑,聚合对象提供迭代器,调用者通过迭代器遍历元素
适用场景需要对象联动通知、存在一对多依赖(关注“状态联动”)需要遍历聚合对象、统一遍历接口(关注“遍历解耦”)
核心角色抽象被观察者、具体被观察者、抽象观察者、具体观察者抽象迭代器、具体迭代器、抽象聚合类、具体聚合类
核心关注点对象间的依赖联动和通知,解耦被观察者与观察者聚合对象的遍历逻辑,解耦聚合与遍历

一句话总结:观察者模式管“状态联动通知”,迭代器模式管“聚合遍历解耦”;需要对象联动、状态变化通知用观察者模式,需要遍历聚合对象、统一遍历接口用迭代器模式,两者可结合使用(如遍历聚合对象时,当聚合对象状态变化,通过观察者模式通知所有关注该聚合对象的观察者)。

七、观察者模式的常见坑与避坑指南

坑1:通知顺序混乱,导致业务逻辑异常
观察者模式中,被观察者通知观察者时,默认按观察者的注册顺序依次通知,若不同观察者的更新逻辑存在依赖关系,通知顺序混乱会导致业务逻辑异常(如先通知物流模块,再通知库存模块,导致库存未扣减就创建物流单)。
避坑指南:若观察者更新逻辑存在依赖关系,在被观察者中指定观察者的通知顺序(如按优先级排序);或通过引入“事件总线”,统一管理通知顺序,确保依赖的观察者先执行更新。

坑2:观察者过多,导致通知效率低下
若被观察者的观察者数量过多,被观察者通知所有观察者时,会导致通知耗时过长,影响系统性能(如一个公众号有10万订阅者,推送通知时需依次通知所有订阅者)。
避坑指南:对观察者进行分组管理,按分组批量通知;采用异步通知方式(如使用线程池、消息队列),避免同步通知阻塞被观察者;过滤无效观察者(如长期未活跃的订阅者),减少通知数量。

坑3:被观察者与观察者循环依赖,导致死循环
部分开发者在实现时,让观察者的更新逻辑触发被观察者的状态变化,被观察者状态变化后又通知观察者,形成循环依赖,导致死循环(如观察者更新时修改被观察者状态,被观察者再次通知观察者)。
避坑指南:禁止在观察者的update()方法中直接修改被观察者的状态;若必须修改,需添加判断条件,避免循环触发通知;或通过异步通知,打破同步循环依赖。

坑4:忽略观察者的注册与删除逻辑,导致内存泄漏
若观察者不再使用时,未从被观察者的观察者列表中删除,会导致被观察者持有观察者的引用,观察者无法被垃圾回收,引发内存泄漏(如页面关闭后,页面中的观察者未取消订阅)。
避坑指南:在观察者生命周期结束时(如页面关闭、对象销毁),主动调用被观察者的removeObserver()方法,取消订阅;被观察者可定期清理无效观察者(如判断观察者是否为null、是否已销毁)。

坑5:过度使用观察者模式,导致逻辑晦涩
部分开发者在不存在一对多依赖、无需联动通知的场景中,强行使用观察者模式,新增抽象被观察者、具体被观察者、抽象观察者等角色,导致代码冗余、逻辑晦涩,降低了代码的可读性和可维护性。
避坑指南:只有当存在一对多依赖、需要联动通知,且需要解耦被观察者与观察者时,才使用观察者模式;简单的对象交互(如一对一依赖),直接调用方法即可,无需过度设计。

八、系列文章预告

本篇文章,我们详细讲解了观察者模式的核心定义、四大核心角色、标准执行流程、微信公众号推送实战代码、高频应用场景和避坑指南,同时区分了易混淆的迭代器模式。观察者模式凭借“联动通知、解耦依赖”的优势,成为事件驱动、消息通知、业务联动场景的首选设计模式,能够大幅提升系统的灵活性和可扩展性,也是开源框架底层、消息系统的核心设计思想之一。
下一篇,我们将学习行为型模式的第二十一种常用模式——状态模式,它的核心是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式专注于“对象状态与行为的联动”,广泛应用于状态变化频繁、行为随状态变化的场景,如订单状态流转、电梯运行状态控制、播放器状态管理等。
状态模式——状态驱动行为,灵活管理对象状态。我们不见不散!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询