适配器Adapter或者Wrapper

  • 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • A类中的a方法,要用到另一个场景下,可能不能兼容,这时我们可以创建B类,持有A对象,并提供b方法,里面调用a方法。
  • b方法是与场景兼容的,所以我们就成功地把A类移植到了一个新场景

桥接

  • 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  1. ┌───────────┐
  2. Car
  3. └───────────┘
  4. ┌───────────┐ ┌─────────┐
  5. RefinedCar ─>│ Engine
  6. └───────────┘ └─────────┘
  7. ┌────────┼────────┐ ┌──────────────┐
  8. ├─│ FuelEngine
  9. ┌───────┐┌───────┐┌───────┐ └──────────────┘
  10. BigCar ││TinyCar││BossCar ┌──────────────┐
  11. └───────┘└───────┘└───────┘ ├─│ElectricEngine
  12. └──────────────┘
  13. ┌──────────────┐
  14. └─│ HybridEngine
  15. └──────────────┘
  • 如上图,RefinedCar有Engine接口的引用
  • 要新增一种品牌的car,只需要新增一个RefinedCar的实现
  • 要新增一种引擎,只要新增一种Engine的接口实现

组合Composite

  • 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
  • 组合模式(Composite)经常用于树形结构,为了简化代码,使用Composite可以把一个叶子节点与一个父节点统一起来处理。

装饰器Decorator

动态地给对象增加一些别的额外职责

  • 优点:
    • 在不改变原有代码的情况下,把类的核心功能和装饰功能区分开了,并能动态扩展一个对象的新功能
    • 有效将类的核心职责和装饰功能让分离开来,也可以去除相关类中重复的装饰逻辑
  • 缺点:

    • 对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

      外观Facade

  • 如果客户端要跟许多子系统打交道,那么客户端需要了解各个子系统的接口,比较麻烦。

  • 如果有一个统一的“中介”,让客户端只跟中介打交道,中介再去跟各个子系统打交道,对客户端来说就比较简单。所以Facade就相当于搞了一个中介。

享元Flyweight

  • 运用共享技术有效地支持大量细粒度的对象。
  • 如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。
  • 享元模式的设计思想是尽量复用已创建的对象,常用于工厂方法内部的优化。
  • Integer.valueOf(12) 很有可能不会新建一个对象,而是返回内存中已经存在的Integer实例(在-128到127之间的int值,都会被缓存)

代理

  • 为其他对象提供一种代理以控制对这个对象的访问。
  • 与Adapter类似,都是B类持有一个A对象
  • 但是这里的代理B类,实现的还是a方法
  • 代理模式通过封装一个已有接口,并向调用方返回相同的接口类型,能让调用方在不改变任何代码的前提下增强某些功能(例如,鉴权、延迟加载、连接池复用等)。
  • 使用Proxy模式要求调用方持有接口,作为Proxy的类也必须实现相同的接口类型。
  • 使用代理模式,实现连接池,close时,不真正关闭连接