【西瓜带你学设计模式 | 第十期 - 外观模式】外观模式 —— 子系统封装实现、优缺点与适用场景
文章目录前言1. 外观模式是什么2. 外观模式能解决什么问题3. 实现思路4. 示例4.1 子系统多个复杂模块4.2 外观类Facade统一入口4.3 客户端调用不需要关心内部细节5. 外观模式的典型结构6. 优缺点6.1 优点6.2 缺点7. 外观模式与代理模式/装饰器模式的区别8. 适用场景9. 总结前言在软件开发中很多系统都会暴露出“很复杂的子系统调用方式”比如要先创建多个对象、按顺序执行多步流程、还要处理很多细节参数。如果客户端每次都要直接面对这些细节就会导致调用方代码臃肿、难维护子系统内部变化会“牵连”调用方学习成本高、可用性差外观模式Facade Pattern就是为了解决这一类问题用一个“外观类”把复杂子系统包装起来给客户端提供一个统一、简洁的入口。1. 外观模式是什么外观模式为子系统中的一组接口提供一个一致的高层接口使得子系统更容易使用。它的本质是“封装复杂度”不需要知道内部怎么做只需要调用外观提供的方法即可。2. 外观模式能解决什么问题外观模式通常用于以下场景隐藏复杂性把多个步骤、多个模块的调用流程封装成一个方法减少耦合客户端不直接依赖复杂子系统的类只依赖 Facade提升可读性/可维护性业务方只关注“我要什么结果”而不是“怎么一步步实现”便于演进子系统内部替换/升级时只需要调整 Facade客户端通常不受影响3. 实现思路实现时通常遵循先有多个“子系统”类子系统A、子系统B、子系统C...再定义一个“外观类”FacadeFacade里封装一套统一的流程把对多个子系统类的调用整合起来客户端只与Facade交互4. 示例这里用一个经典场景家庭影院系统播放电影需要音响、投影、播放器等按顺序协作。4.1 子系统多个复杂模块classProjector{publicvoidon(){System.out.println(投影仪开机);}publicvoidsetInput(Stringinput){System.out.println(投影仪设置输入源input);}}classSoundSystem{publicvoidon(){System.out.println(音响开机);}publicvoidsetVolume(intvolume){System.out.println(音响音量volume);}}classPlayer{publicvoidon(){System.out.println(播放器启动);}publicvoidplay(Stringmovie){System.out.println(开始播放movie);}}4.2 外观类Facade统一入口publicclassHomeTheaterFacade{privatefinalProjectorprojector;privatefinalSoundSystemsoundSystem;privatefinalPlayerplayer;publicHomeTheaterFacade(Projectorprojector,SoundSystemsoundSystem,Playerplayer){this.projectorprojector;this.soundSystemsoundSystem;this.playerplayer;}// 外观提供给客户端的简单方法一键播放publicvoidplayMovie(Stringmovie){// 内部复杂流程都封装在这里projector.on();projector.setInput(HDMI1);soundSystem.on();soundSystem.setVolume(8);player.on();player.play(movie);System.out.println(家庭影院播放流程已完成);}}4.3 客户端调用不需要关心内部细节publicclassClient{publicstaticvoidmain(String[]args){HomeTheaterFacadefacadenewHomeTheaterFacade(newProjector(),newSoundSystem(),newPlayer());facade.playMovie(Inception);}}客户端只做一件事调用playMovie()无需关心投影仪/音响/播放器的细节顺序。5. 外观模式的典型结构Facade外观统一入口对外提供简化方法Subsystem子系统具体实现细节由 Facade 编排调用Client客户端只依赖 Facade6. 优缺点6.1 优点降低复杂度客户端只关心 Facade 的简单接口减少耦合客户端不直接依赖子系统实现细节更易演进子系统变化集中在 Facade 里处理6.2 缺点Facade 可能变得臃肿做太多“流程编排”导致外观类越来越大可能掩盖灵活性客户端不再直接访问子系统某些高级用法会受限7. 外观模式与代理模式/装饰器模式的区别外观模式Facade重点是“把一堆复杂调用变成一个简单入口”属于结构性封装。代理模式Proxy重点是“代表/控制访问”常见用途是权限、远程、缓存、延迟等。装饰器模式Decorator重点是“动态叠加功能”强调在不改变原对象基础上逐层增强行为。一句话记忆Facade让你“更好用”简化接口Proxy替你“管控访问/转发”代表与控制Decorator给你“加功能”扩展职责8. 适用场景适合子系统复杂且要提供统一调用方式多个模块需要固定流程编排例如初始化、启动、发布希望降低模块之间的耦合不太适合所有逻辑都集中到 Facade导致“上帝类”客户端需要频繁使用子系统的细粒度能力那外观可能无法覆盖所有需求9. 总结外观模式就是用一个 Facade 类把复杂子系统封装起来给客户端提供简单统一的高层接口。