设计模式系列文章(基础篇第30篇):观察者模式——对象联动通知,解耦依赖关系
大家好欢迎来到设计模式系列文章基础篇的第三十篇内容。在上一篇中我们学习了行为型模式的第十九种常用模式——迭代器模式其核心是分离聚合对象与遍历逻辑提供统一的遍历接口实现遍历与聚合的解耦广泛应用于集合遍历、自定义容器等场景。今天我们将学习行为型模式的第二十种常用模式——观察者模式它的核心是定义对象间的一对多依赖关系当一个对象被观察者的状态发生变化时所有依赖它的对象观察者都会得到通知并自动更新实现对象间的联动通知同时解耦被观察者与观察者的依赖关系。在日常开发和生活中观察者模式的应用无处不在。比如我们关注的微信公众号公众号被观察者发布新文章时所有关注该公众号的用户观察者都会收到推送通知用户无需主动查询就能及时获取最新内容再比如电商系统中的订单状态变更当订单状态从“待付款”变为“已付款”时库存系统观察者会自动扣减库存物流系统观察者会自动创建物流单消息系统观察者会向用户发送支付成功通知还有生活中的天气预报气象站被观察者监测到天气变化后会向所有订阅了天气预报的设备观察者推送最新天气信息。这些场景的核心需求是“对象状态变化时联动通知所有依赖对象并触发更新”若直接让被观察者与每个观察者建立直接依赖会导致两者耦合过高——当新增、删除观察者时需要修改被观察者的代码违背开闭原则同时被观察者需要知道所有观察者的存在增加了系统的维护成本。观察者模式则通过引入“抽象被观察者”和“抽象观察者”将被观察者与观察者解耦被观察者只需通知抽象观察者无需关心具体观察者的实现观察者只需实现抽象观察者接口无需关心被观察者的具体逻辑大幅提升了系统的灵活性和可扩展性。今天我们就从核心定义、结构、实战实现、场景对比、避坑指南全维度讲解帮大家彻底掌握这种“对象联动通知”的实用设计模式。一、观察者模式的核心定义与设计初衷1. 核心定义观察者模式Observer Pattern定义对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都得到通知并被自动更新。观察者模式又称发布-订阅模式Publish/Subscribe Pattern核心是解耦被观察者与观察者实现状态变化的联动通知确保观察者与被观察者各自独立扩展。通俗理解观察者模式就像我们生活中的“订阅报纸”报社被观察者负责发布报纸订阅报纸的读者观察者会定期收到报纸读者无需关心报社的报纸制作、发行流程只需订阅即可当报社发布新报纸状态变化时所有订阅的读者都会收到通知并获取报纸读者可以随时订阅、取消订阅报社无需修改自身逻辑只需维护订阅列表即可。再比如班级群通知老师被观察者在群里发送通知状态变化所有进群的学生观察者都会收到通知学生可以随时进群、退群老师无需关心具体有多少学生只需发送通知即可。2. 设计初衷解决的核心问题观察者模式的出现核心是解决“对象间存在一对多依赖、状态变化需要联动通知且耦合度高”的痛点具体解决3个核心问题解耦依赖关系被观察者无需知道具体观察者的实现只需依赖抽象观察者观察者无需知道被观察者的具体逻辑只需依赖抽象被观察者实现两者的解耦实现联动通知当被观察者的状态发生变化时自动通知所有注册的观察者触发观察者的更新操作无需手动调用实现状态联动灵活扩展新增、删除观察者时无需修改被观察者的代码只需新增、删除观察者对象并注册到被观察者符合开闭原则被观察者和观察者可独立扩展自身逻辑互不影响。3. 设计原则适配观察者模式严格贴合面向对象设计核心原则尤其在“开闭原则”和“依赖倒转原则”上表现突出是实现对象联动通知的最佳实践开闭原则新增观察者或被观察者时无需修改原有代码只需新增对应的类并实现抽象接口扩展性强依赖倒转原则被观察者依赖抽象观察者不依赖具体观察者观察者依赖抽象被观察者不依赖具体被观察者降低了耦合度单一职责原则被观察者只负责维护自身状态和通知观察者观察者只负责接收通知并执行自身的更新逻辑各司其职迪米特法则最少知道原则被观察者只需知道抽象观察者的接口无需知道具体观察者的内部实现观察者只需知道抽象被观察者的接口无需知道被观察者的内部状态和实现逻辑。二、观察者模式的核心结构4个核心角色观察者模式的结构围绕“被观察者状态变化、通知观察者更新”展开核心包含4个角色各司其职、协同完成对象间的联动通知我们以“微信公众号推送”为场景逐一拆解角色职责与交互逻辑1. 抽象被观察者Subject所有具体被观察者的抽象父类或接口定义了管理观察者的核心方法注册观察者、删除观察者和通知观察者的方法。抽象被观察者维护一个观察者列表负责注册、删除观察者并在自身状态变化时通知所有注册的观察者。对应微信公众号场景中的“抽象公众号”定义注册订阅者、删除订阅者、推送通知的接口。2. 具体被观察者Concrete Subject实现抽象被观察者接口维护自身的状态当自身状态发生变化时调用通知方法向所有注册的观察者发送通知。具体被观察者是状态变化的触发者负责维护观察者列表并在状态变化时触发联动通知。对应微信公众号场景中的“具体微信公众号”维护公众号的文章状态当发布新文章状态变化时向所有订阅者推送通知。3. 抽象观察者Observer所有具体观察者的抽象父类或接口定义了观察者接收通知并执行更新操作的方法。抽象观察者规范了观察者的核心行为确保所有具体观察者都能响应被观察者的通知。对应微信公众号场景中的“抽象订阅者”定义接收公众号推送通知的接口。4. 具体观察者Concrete Observer实现抽象观察者接口是依赖于被观察者的对象当接收到被观察者的通知时执行自身的更新操作如接收推送、处理业务逻辑。具体观察者不关心被观察者的状态变化细节只需在收到通知后执行自身的业务逻辑。对应微信公众号场景中的“具体订阅者”接收公众号的推送通知并显示文章内容。核心关系总结抽象被观察者定义观察者管理和通知规范具体被观察者实现状态管理和通知逻辑抽象观察者定义接收通知和更新的规范具体观察者实现更新逻辑。具体被观察者维护观察者列表注册、删除具体观察者当具体被观察者状态变化时调用通知方法触发所有注册的具体观察者执行更新操作被观察者与观察者通过抽象接口解耦可独立扩展。三、观察者模式的核心逻辑与执行流程观察者模式的核心逻辑是“一对多依赖、状态联动通知、解耦依赖关系”标准执行流程分为六步全程实现被观察者与观察者的解耦逻辑闭环我们以“微信公众号推送新文章”为例拆解执行流程定义抽象观察者接口声明接收通知并执行更新操作的方法定义抽象被观察者接口声明注册观察者、删除观察者、通知观察者的方法实现具体被观察者维护自身状态和观察者列表实现注册、删除观察者的方法在状态变化时调用通知方法实现具体观察者实现抽象观察者的更新方法接收被观察者的通知并执行自身逻辑注册观察者创建具体被观察者和具体观察者将具体观察者注册到具体被观察者的观察者列表中触发通知具体被观察者的状态发生变化调用通知方法向所有注册的具体观察者发送通知具体观察者接收通知并执行更新操作。关键要点具体被观察者只负责维护观察者列表和通知观察者不关心观察者的具体更新逻辑具体观察者只负责接收通知并执行自身更新逻辑不关心被观察者的状态变化细节新增观察者时只需创建具体观察者并注册到被观察者无需修改被观察者代码被观察者与观察者通过抽象接口解耦确保两者可独立扩展。四、观察者模式的实战实现微信公众号推送场景我们以高频的微信公众号推送为场景使用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 Observer1手机用户订阅者// 具体观察者手机用户订阅者接收公众号推送并显示文章摘要 public class MobileUser implements Observer{// 订阅者用户名 private String username;// 构造方法初始化用户名 public MobileUser(String username){this.usernameusername;}// 接收通知显示文章摘要手机端适配 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.usernameusername;}// 接收通知显示完整文章电脑端适配 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 ListObserverobserverListnew ArrayList();// 构造方法初始化公众号名称 public WeChatOfficialAccount(String accountName){this.accountNameaccountName;}// 注册订阅者添加观察者到列表 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!nullobserverList.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 officialAccountnew WeChatOfficialAccount(设计模式学习指南);//2. 创建具体观察者订阅者 Observer mobileUser1new MobileUser(张三);Observer mobileUser2new MobileUser(李四);Observer computerUser1new ComputerUser(王五);Observer computerUser2new 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 padUsernew PadUser(孙七);officialAccount.registerObserver(padUser);((WeChatOfficialAccount)officialAccount).publishArticle(观察者模式避坑指南,本文总结了观察者模式的5个常见坑及避坑指南帮助大家在实际开发中规避问题...此处省略600字);}// 新增具体观察者平板用户无需修改公众号代码体现扩展性 static class PadUser implements Observer{private String username;public PadUser(String username){this.usernameusername;}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 SwingSwing的事件监听机制如ActionListener、MouseListener本质是观察者模式RxJava/RxAndroid基于响应式编程核心是观察者模式实现数据流的联动通知和处理。六、观察者模式 vs 迭代器模式重点区分观察者模式与上一篇学习的迭代器模式都属于行为型模式且都涉及“对象间的交互与解耦”但核心目标、使用场景、核心逻辑完全不同极易混淆通过表格清晰对比帮大家彻底区分对比维度观察者模式迭代器模式核心目标定义一对多依赖实现被观察者状态变化时的联动通知解耦依赖关系分离聚合与遍历逻辑提供统一遍历接口实现遍历解耦核心逻辑被观察者维护观察者列表状态变化时通知所有观察者观察者执行更新迭代器封装遍历逻辑聚合对象提供迭代器调用者通过迭代器遍历元素适用场景需要对象联动通知、存在一对多依赖关注“状态联动”需要遍历聚合对象、统一遍历接口关注“遍历解耦”核心角色抽象被观察者、具体被观察者、抽象观察者、具体观察者抽象迭代器、具体迭代器、抽象聚合类、具体聚合类核心关注点对象间的依赖联动和通知解耦被观察者与观察者聚合对象的遍历逻辑解耦聚合与遍历一句话总结观察者模式管“状态联动通知”迭代器模式管“聚合遍历解耦”需要对象联动、状态变化通知用观察者模式需要遍历聚合对象、统一遍历接口用迭代器模式两者可结合使用如遍历聚合对象时当聚合对象状态变化通过观察者模式通知所有关注该聚合对象的观察者。七、观察者模式的常见坑与避坑指南坑1通知顺序混乱导致业务逻辑异常观察者模式中被观察者通知观察者时默认按观察者的注册顺序依次通知若不同观察者的更新逻辑存在依赖关系通知顺序混乱会导致业务逻辑异常如先通知物流模块再通知库存模块导致库存未扣减就创建物流单。避坑指南若观察者更新逻辑存在依赖关系在被观察者中指定观察者的通知顺序如按优先级排序或通过引入“事件总线”统一管理通知顺序确保依赖的观察者先执行更新。坑2观察者过多导致通知效率低下若被观察者的观察者数量过多被观察者通知所有观察者时会导致通知耗时过长影响系统性能如一个公众号有10万订阅者推送通知时需依次通知所有订阅者。避坑指南对观察者进行分组管理按分组批量通知采用异步通知方式如使用线程池、消息队列避免同步通知阻塞被观察者过滤无效观察者如长期未活跃的订阅者减少通知数量。坑3被观察者与观察者循环依赖导致死循环部分开发者在实现时让观察者的更新逻辑触发被观察者的状态变化被观察者状态变化后又通知观察者形成循环依赖导致死循环如观察者更新时修改被观察者状态被观察者再次通知观察者。避坑指南禁止在观察者的update()方法中直接修改被观察者的状态若必须修改需添加判断条件避免循环触发通知或通过异步通知打破同步循环依赖。坑4忽略观察者的注册与删除逻辑导致内存泄漏若观察者不再使用时未从被观察者的观察者列表中删除会导致被观察者持有观察者的引用观察者无法被垃圾回收引发内存泄漏如页面关闭后页面中的观察者未取消订阅。避坑指南在观察者生命周期结束时如页面关闭、对象销毁主动调用被观察者的removeObserver()方法取消订阅被观察者可定期清理无效观察者如判断观察者是否为null、是否已销毁。坑5过度使用观察者模式导致逻辑晦涩部分开发者在不存在一对多依赖、无需联动通知的场景中强行使用观察者模式新增抽象被观察者、具体被观察者、抽象观察者等角色导致代码冗余、逻辑晦涩降低了代码的可读性和可维护性。避坑指南只有当存在一对多依赖、需要联动通知且需要解耦被观察者与观察者时才使用观察者模式简单的对象交互如一对一依赖直接调用方法即可无需过度设计。八、系列文章预告本篇文章我们详细讲解了观察者模式的核心定义、四大核心角色、标准执行流程、微信公众号推送实战代码、高频应用场景和避坑指南同时区分了易混淆的迭代器模式。观察者模式凭借“联动通知、解耦依赖”的优势成为事件驱动、消息通知、业务联动场景的首选设计模式能够大幅提升系统的灵活性和可扩展性也是开源框架底层、消息系统的核心设计思想之一。下一篇我们将学习行为型模式的第二十一种常用模式——状态模式它的核心是允许一个对象在其内部状态改变时改变它的行为对象看起来似乎修改了它的类。状态模式专注于“对象状态与行为的联动”广泛应用于状态变化频繁、行为随状态变化的场景如订单状态流转、电梯运行状态控制、播放器状态管理等。状态模式——状态驱动行为灵活管理对象状态。我们不见不散