2 . 定义用户目标接口 : 用户通过调用该接口 , 实现实际的功能 , 该功能与适配者中的功能类似 , 但 接口不同 ;
3 . 声明适配器 :
① 适配器 实现 用户目标接口 : 适配器 需要实现 用户目标接口 , 在实现的接口方法中 , 需要将实际操作 委托给 被适配者 ;
② 适配器 维护 被适配者 类型成员变量 : 如何调用到 被适配者 的方法呢 , 这里 适配器 通过 定义 被适配者 类型的成员变量 , 通过该 被适配者 类型成员变量 , 调用 被适配者 public 方法 ;
③ 委托操作 : 在实现的 用户目标接口中 , 通过 被适配者类型 成员变量 , 调用 被适配者 的方法实现具体功能 ;
类适配器 与 对象适配器 , 本质区别就是 适配器类访问 被适配者的途径 ;
类适配器 : 通过继承 被适配器 , 获取访问被适配器方法的资格 ;
对象适配器 : 通过在其内部维护一个 被适配者 成员变量 , 进而通过该成员变量访问 被适配者方法 ;
4 . 用户访问操作 :
① 定义目标接口变量 : 定义 用户目标接口 对象变量 ;
② 目标接口变量赋值 : 创建 适配器对象 赋值给上述 用户目标接口对象变量 , ( 适配器 是 用户目标接口 的子类 ) ;
③ 目标接口调用 : 调用用户目标接口 , 即可调用被适配者的实际功能方法 ;
2、装饰者模式
【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )
装饰者模式概念 :
① 设计模式类型 : 结构性 ;
② 概念 : 不改变原有类的对象 , 动态地将额外的功能附加到该对象上 ;
③ 扩展对象功能 : 这种功能扩展方式比类继承更加灵活 ;
④ 装饰者模式 : 移除类中的被装饰功能 , 将被装饰类简化 , 区分类的核心职责 和 装饰功能 ;
装饰者模式适用场景 :
① 功能扩展 : 为一个类扩展功能 , 为其添加额外的职责 ; ( 强调扩展 )
② 动态添加撤销功能 : 为一个对象动态添加额外功能 , 同时这些被添加的功能还能被动态撤销 ; ( 强调动态 )
装饰者模式优点 :
① 扩展灵活 : 使用装饰者模式 , 比继承更加灵活 ; 使用装饰者模式扩展类功能 , 不会改变原来的类 ;
② 排列组合 : 对装饰类进行各种排列组合 , 可实现不同的扩展功能 ;
③ 开闭原则 : 装饰者模式符合开闭原则 , 被装饰的类 , 和装饰类相互独立 , 互不干扰 ;
装饰者模式缺点 :
① 程序复杂 : 需要编写更多的代码 , 生成更多的类 , 程序的复杂性增加了 ;
② 动态 / 多层 装饰 : 动态 / 多层 装饰一个类时 , 程序更复杂 ;
3、代理模式
【设计模式】代理模式 ( 简介 | 适用场景 | 优缺点 | 代理扩展 | 相关设计模式 )
【设计模式】代理模式 ( 静态代理 )
【设计模式】代理模式 ( 动态代理 )
代理模式 : 为 其它对象 提供 一种代理 , 以 控制 对 这个对象 的访问 ;
代理对象 在 客户端 和 目标对象 之间 起到 中介的作用 ;
如 : 租客通过中介找房东租房子 , 房东将房子托管给了中介 , 房东是目标对象 , 但是租赁行为是中介来执行的 , 中介是代理类 , 租客 就是 客户端 ;
中介 代理 房东 进行租赁行为 , 相当于 代理类对目标对象进行了增强 ;
客户端 通过 代理类 与 目标对象 进行交互 , 客户端 不直接接触 目标对象 ;
代理模式类型 : 结构性 ;
代理模式适用场景 :
保护目标对象 : 客户端 只与 代理类 进行交互 , 不清楚 目标对象 的具体细节 ; 相当于 租客 只与 中介 进行交互 , 不知道房东的信息 ;
增强目标对象 : 代理类 在 目标对象的基础上 , 对 目标对象的功能 进行增强 ;
代理模式优点 :
分离目标对象 : 代理模式 能将 代理对象 与 真实被调用的 目标对象 分离 ;
降低耦合 : 在一定程度上 , 降低了系统耦合性 , 扩展性好 ;
保护目标对象 : 代理类 代理目标对象的业务逻辑 , 客户端 直接与 代理类 进行交互 , 客户端 与 实际的目标对象之间没有关联 ;
增强目标对象 : 代理类 可以 在 目标对象基础上 , 添加新的功能 ;
代理模式缺点 :
类个数增加 : 代理模式 会 造成 系统中 类的个数 增加 , 比不使用代理模式增加了代理类 , 系统的复杂度增加 ; ( 所有的设计模式都有这个缺点 )
性能降低 : 在 客户端 和 目标对象 之间 , 增加了一个代理对象 , 造成 请求处理速度变慢 ;
静态代理 : 在代码中 , 使用指定的代理 ; 显示的定义了一个业务实现类代理 ; 在代理类中 , 对同名的业务方法进行包装 , 用户通过调用 代理类中 被包装过的业务逻辑方法 , 来调用 被包装对象 的业务方法 , 同时对目标对象的业务方法进行增强 ;
动态代理 : 由 JDK 提供 , 只能对 实现的接口的类 进行动态代理 , 不能代理具体的实现类 ; 通过 接口 中的 方法名 , 在 动态生成的 代理类 中 , 调用 业务实现类 的 同名方法 ;
JDK 动态代理 , 用到的代理类 , 是在程序调 用到代理对象时 , 由 Java 虚拟机创建 , Java 虚拟机 根据传入的 业务实现类对象 以及 方法名 , 动态地创建代理类 Class 文件 , 当该 Class 文件被字节码引擎执行 , 通过该代理类对象进行目标方法的调用 ;
动态代理无法代理类 , 只可以代理接口 ;
CGLib 代理 : 可以 针对类实现进行代理 ;
如果要 代理一个类 , CGLib 会生成一个被代理类的子类 , 通过 继承该类 并 覆盖其中的方法 ;
如果该类时 final 的 , 则无法被继承 , 如果类中的方法是 final 的 , 该方法无法被重写 ;
使用 CGLib 代理要特别注意 final 修饰符 ;
4、外观模式
【设计模式】外观模式 ( 概念 | 适用场景 | 优缺点 | 代码示例 )
1 . 外观模式概念 :
① 设计模式类型 : 结构型 ;
② 标准定义 : 提供一个统一接口 , 用于访问子系统中的一群接口 ;
③ 隐藏复杂性目的 : 定义高层级接口 , 让子系统更容易使用 , 目的是隐藏系统的复杂性 ;
④ 交互流程 : 多个子系统联合完成一个操作 , 提供一个统一的接口 , 供客户端调用 , 客户端不与每个子系统进行复杂的交互 , 客户端只与提供接口的外观类进行交互 ;
2 . 外观模式的相关角色 :
① 外观角色 : 外观类有自己的方法 , 用户可以通过调用外观类的方法 , 调用子系统提供的功能 ;
② 子系统角色 : 可以是若干个处理模块 , 数量 1 个或多个 ;
③ 用户角色 : 用户通过外观类调用子系统的功能 ;
外观模式适用场景 :
① 子系统复杂 : 子系统复杂 , 通过使用外观模式可以简化调用接口 ;
② 层次复杂 : 系统结构层次复杂 , 每个层级都一个使用外观对象作为该层入口 , 可以简化层次间的调用接口 ;
5、桥接模式
【设计模式】桥接模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
桥接模式 :
分离抽象实现 : 将 抽象部分 与 它的 具体实现部分 分离 , 使它们 都可以 独立的 变化 ; 独立的变化 就是 在一定程度上 进行解耦 ;
组合方式 : 通过 组合 的方式 建立 两个类 之间的联系 , 而 不是 继承 ;
桥接模式类型 : 结构型 ;
桥接模式 相当于 使用桥梁 将两侧连接起来 , 这里指的是 使用桥梁 连接两个类 , 在两个类之间建立某种联系 , 可以通过继承 , 也可以通过组合 , 桥接模式 是采用 组合的方式 , 建立两个类之间的关系 ; 合成复用原则 , 推荐优先使用组合 , 不是继承 ; 桥接模式 可以防止子类过多 , 造成系统复杂的情况 ;
桥接模式的重点 是 理解 类的 抽象部分 和 具体的实现部分 ;
抽象过程 : 抽象部分 , 经过 抽象化 , 忽略某些信息 , 将不同的实体当做同一个对待 ; 面向对象中 , 将对象的共同性质抽取出来 , 形成类的过程 , 就是抽象化过程 ;
实现过程 : 对于具体实现的部分 , 也要进行实现化 , 针对抽象化 , 给出具体实现 ; 这个过程就是实现过程 , 过程的产出就是具体实现部分 , 具体实现部分产生的对象 , 比抽象产生的更具体 , 是对抽象化事物的具体化产物 ;
如 : 开发跨平台的视频播放器 , 平台有 Android , iOS , Windows , Linux , Mac , 播放器支持的格式有 MP4 , AVI , RMVB , FLV 格式 ; 这种情况下 , 适合使用桥接模式 ;
桥接模式适用场景 :
抽象实现灵活 : 抽象 和 具体实现 之间 , 需要 增加更多灵活性 的情况下 , 适合使用桥接模式 ;
使用 桥接模式 , 可以 避免在这两个层次之间 , 建立静态的继承关系 , 通过 桥接模式 在二者之间建立 关联关系 ;
抽象 和 实现 都可以 各自 以继承的方式扩展 , 互不影响 ;
可以动态的 将 抽象 的子类对象 和 实现 的子类对象 进行组合 , 在系统中 , 抽象 和 实现 之间进行了解耦 ;
独立变化维度 : 一个类存在 2 22 个或更多的 独立变化维度 , 并且这些维度都需要 独立扩展 ;
抽象部分可以 独立扩展 , 具体实现的部分 , 也可以独立扩展 ;
不使用继承 : 不希望使用继承 , 或 因多层继承导致系统类的个数增加 ;