第10章 · 播客 第2集

设计模式 · 结构型模式

🎙️ 本集播客第2集:结构型七模式——Adapter 转接口、Bridge 抽象与实现分离、Composite 树形组合、Flyweight 省空间费时间、Proxy 管访问;深挖 Decorator(动态加功能、比继承更灵活)与 Facade(加一层统一入口、Session Facade 减少远程调用),最后把 23 个模式的三类归属大辨析做穿,给一个模式名就能报出类别。 语音由微软 Edge 神经网络语音预生成(女声·晓伊,男声·云希)。点击下方任意对话可直接从该句开始播,当前句朗读时下一句已预先加载,无缝衔接。
🎙️ 第10章播客 第2集
⬇ 下载本集 点击播放
小雅
上一集把创建型讲完了——工厂和单例管的是「对象怎么生出来」。这一集进第二类:结构型设计模式。原文说,系统不断扩张、模块复用增多,类与对象的结构越来越复杂,缺乏良好设计时类之间的关系会非常混乱——结构型解决的就是「类与对象怎么组织」。
阿明
结构型一共几个?
小雅
七个,按原文顺序:Adapter 适配器、Bridge 桥接、Composite 组合、Decorator 装饰、Facade 外观、Flyweight 享元、Proxy 代理。立个硬要求:七个名字要能张口报出来,考试爱反着考——给模式名问类别。今天深挖原文详解的 Decorator 和 Facade,另外五个各记一句意图。
小雅
先说 Adapter。原文:可以解决系统间接口不相容的问题,把类的接口转化为客户程序所希望的接口,从而提高复用性。判别词「接口不相容、转化接口」。什么时候用?现成的类接口跟客户要的对不上,又不想动原有代码,就加一层转接。
阿明
相当于一个转接头。Bridge 呢?
小雅
Bridge:把类的抽象部分同实现部分相分离,抽象和实现都可以独立地变化。判别词「抽象与实现分离、独立变化」,选项里见到就选 Bridge。
小雅
Composite:以树形结构组合对象,使单个对象和组合后的对象具有一致性,提高复用性。判别词「树形结构」。原文总结里还类比:绝大多数的组织看起来都像 Composite。
阿明
树形结构这个特征词太好认了。下一个。
小雅
Flyweight:共享大量的细粒度对象,节省创建对象分配的空间,不过在时间上的开销会变大。省了空间、费了时间——效果题爱把「时间开销变小」当错项。
小雅
Proxy:为对象提供访问代理,控制客户程序的访问——访问权限、访问地址、访问方式的控制,甚至把开销较大的访问化整为零、提高访问效率。原文类比:经纪人与 Proxy 非常相近。
阿明
我发现 Adapter、Decorator、Proxy 都是「包一层」,考试会不会拿这个坑我们?
小雅
会,这是结构型最经典的坑。三个都包一层,分工不同:Adapter 接口不一样,把接口转化成客户希望的——掰接口;Decorator 接口一样,动态往方法上加功能——加料;Proxy 接口一样,站在门口控制访问——查证件。三句话:转接口、加功能、管访问。
阿明
行,这三句记下了。Decorator 往深里讲讲吧。
小雅
Decorator 又称装饰模式或油漆工模式。它解决的问题:类预先设计的功能不够强大,需要增强或扩展。最简单的办法是继承新类扩展方法,但会产生大量子类,让类层次结构变得复杂且混乱。Decorator 的思路是在原有类的基础上包装一层来解决功能扩展。
小雅
结构角色记四个:抽象类 Component 是共同父类;ConcreteComponent 是具体构件、被装饰的对象;DecoratorComponent 是装饰类,和 ConcreteComponent 继承自同一个 Component、拥有相同接口;装饰不止一种,又继承出 ConcreteDecorator1、ConcreteDecorator2。原文说这个结构在类层次上很清晰,比静态继承更具有灵活性。
小雅
工作原理一句话:接口相同的 operation 方法,在运行期根据客户的选择具有不同的行为特征,实现功能动态的扩展。Decorator 的关键词就是「动态」——继承是编译期定死的,装饰是运行期套上去的。
阿明
考「Decorator 的主要优点」,A 是保证有且仅有一个实例,C 是动态扩展类功能、避免继承出大量子类——C 对上了。
小雅
对,答案就是 C:动态扩展类的功能,同时避免继承出大量的子类,比继承的方法更灵活。拆干扰项:A「有且仅有一个实例」是 Singleton 的效果,创建型;B「封装子系统接口、降低耦合」是 Facade 的话术,留给下一个模式;D「减少对象间的耦合性」是 Mediator 的主要优点,行为型。杀招就是把三个别的模式的招牌效果凑成一个选项盘。
小雅
Decorator 的缺点也要会选:大量使用会造成系统中出现很多接口类似的小装饰对象,造成可维护性的下降。应用例子记两个——JDK 的 I/O API 和 displaytag 开源项目。
阿明
懂了,优点缺点都拿「小对象、可维护性」说事。接下来是 Facade 吧,跟 J2EE 那个 Session Facade 连着的。
小雅
Facade 又称外观模式,也有人称门面模式。它解决的问题:程序经常要用到其他若干子系统,不作处理时得了解每个子系统的接口并逐个调用,结构混乱,客户程序和子系统的耦合性大大增加,扩展与维护都相当困难。
小雅
解决手法是原文原话:Facade 模式通过在原有系统前增加一层的方法,封装这些子系统的接口,对外提供一致的访问接口。这就是考题「Facade 的核心思想」的标准答案。三个关键词:加一层、封装子系统、一致接口,一个不能丢。
阿明
这道题的另外三个选项正好都是结构型模式的效果——抽象与实现分离是 Bridge,树形结构组合对象是 Composite,共享细粒度对象是 Flyweight。
小雅
看得准。这道题四个选项全是结构型句式,干扰不在类别,而在「哪句话配哪个模式」。Facade 的效果再补两句原文:屏蔽子系统细节,降低客户程序使用子系统的复杂度,也降低客户程序和子系统的耦合——从让所有人了解所有子系统接口,变成让个别专家抽象子系统接口。应用的关键是抽象出合理的 Facade 接口,原文例子是对数据访问对象 DAO 封装,使数据访问同具体的数据库相分离。
小雅
然后是 Session Facade,EJB 领域从 Facade 引申的。背景:EJB 是分布式构件,J2EE 将对 EJB 的访问定义为远程访问——即使 Servlet 和 EJB 部署在同一台主机,因为分置于不同的容器,默认也通过本机回播地址 127.0.0.1 访问,有效率问题。所以把 Session Bean 和 Facade 结合,封装业务逻辑的接口,形成 Session Facade。
阿明
它的主要作用是不是「减少远程调用」?
小雅
正是,考点原话:除了获得 Facade 模式的优点外,还可以减少远程调用 EJB 的次数,降低网络接口的负载,提高性能。考题问主要作用,选「用 Session Bean 封装业务逻辑,减少远程调用次数,提高性能」。干扰项「保证系统中只有一个 EJB 实例」是把 Singleton 的效果搬过来;「截取客户请求进行预处理」是 Intercepting Filter 的活儿。
小雅
补充机制细节:Session Facade 中一般用 Session Bean 作为业务逻辑的接口,在 SessionBean 中做事务处理,确保客户每一次访问即完成一次业务操作,同时减少内部业务逻辑和外部访问者的耦合,封装服务器中的对象模型。
阿明
那 Intercepting Filter 跟 Decorator 长得也很像啊,原文好像自己都提到了。
小雅
原文相关讨论原话:它与 Decorator 模式有些类似,都是在真正的处理对象前增加一层扩展对象的操作,只不过实现起来有很大的差别。对应一道题——Intercepting Filter 与哪个模式在实现上有相似之处,答案 Decorator。区分点:Intercepting Filter 截取客户请求、送进 Filter 链一步步预处理、完了才转发给真正响应的 Servlet;Decorator 是给对象方法动态加功能。
阿明
你开头说考试爱反着考分类,就是那道「以下哪个属于 GoF 结构型设计模式」的题吧?
小雅
对,选项四个:Singleton 单例、Observer 观察者、Adapter 适配器、Command 命令,答案 Adapter——结构型七兄弟之一。Singleton 是创建型,管生对象;Observer 和 Command 是行为型,管对象之间怎么通信。这种题不考细节,考归类,我们把三类一次理清。
小雅
原文的分类依据要记牢:面向对象设计要解决三个问题——如何管理系统中的对象、如何组织系统中的类与对象、类与对象如何相互通信。创建型对应第一问,解决对象创建;结构型对应第二问,解决类与对象的组织;行为型对应第三问,解决对象通信。三问对三类。
阿明
拿模式名来考我吧,先考结构型。
小雅
判定结构型最快的抓手:凡讲「接口转化、抽象实现分离、树形组合、动态加功能、统一访问入口、共享省空间、访问控制」的都是结构型——说的都是类怎么组织、怎么搭。所以 Adapter、Bridge、Composite、Decorator、Facade、Flyweight、Proxy,报结构型。
小雅
再反过来记两类,排除法就稳了。创建型五个,全跟「创建、实例、工厂」沾边:Factory Method 延迟创建、Abstract Factory 抽象工厂、Builder 逐步构造复杂对象、Prototype 深复制原型创建新对象、Singleton 保证一个类仅有一个实例——带 Factory、Builder、Prototype、Singleton 字样,创建型。
小雅
行为型十一个,全是「消息、请求、状态、算法、访问」的戏:Interpreter 解释文法、Template Method 操作模板、Chain of Responsibility 请求在链上传递、Command 将请求封装为对象、Iterator 顺序访问集合、Mediator 中介封装通信、Memento 捕获恢复状态、Observer 状态广播、State 状态改变行为、Strategy 算法独立变化、Visitor 不改元素类定义新操作。
阿明
我总结个判别口诀:Factory 家族和 Singleton 看到就选创建型;带通信、请求、状态、通知、算法的字眼选行为型;剩下的「包一层、组一树、共享一组」就是结构型。
小雅
可以,再钉几个高频易混的。Observer 是行为型,别因为它「广播状态」像结构——它解决的是通信问题;Mediator 也是行为型,第五题的 D 选项就是它的优点;Proxy 和 Decorator 都是结构型,但 Singleton 是创建型,「代理保证唯一实例」这种拼接选项不能信。还有 MVC,原文说它既可以看作设计模式也可以看作架构风格,别往三分类里硬塞。
阿明
这集信息量不小,收个尾吧。
小雅
本集必背:结构型七模式——Adapter 转接口、Bridge 抽象与实现分离、Composite 树形组合、Decorator 动态加功能、Facade 加一层统一入口、Flyweight 共享省空间但费时间、Proxy 控制访问;包一层三兄弟的分工——Adapter 掰接口、Decorator 加料、Proxy 管访问;Decorator 优点是动态扩展、避免大量子类、比继承更灵活,缺点是产生大量小装饰对象难维护。
小雅
再背 Facade:核心是在原有系统前加一层、封装子系统接口、对外一致访问;Session Facade 在 EJB 里减少远程调用、提高性能;Intercepting Filter 实现上与 Decorator 相似。三分类一句话——创建型管对象创建、结构型管类与对象组织、行为型管对象通信。下一集进行为型,细讲 Observer 的 notify、Mediator 的复杂中介。