适配器Adapter或者Wrapper
- 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- A类中的a方法,要用到另一个场景下,可能不能兼容,这时我们可以创建B类,持有A对象,并提供b方法,里面调用a方法。
- b方法是与场景兼容的,所以我们就成功地把A类移植到了一个新场景
桥接
- 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
┌───────────┐
│ Car │
└───────────┘
▲
│
┌───────────┐ ┌─────────┐
│RefinedCar │ ─ ─ ─>│ Engine │
└───────────┘ └─────────┘
▲ ▲
┌────────┼────────┐ │ ┌──────────────┐
│ │ │ ├─│ FuelEngine │
┌───────┐┌───────┐┌───────┐ │ └──────────────┘
│BigCar ││TinyCar││BossCar│ │ ┌──────────────┐
└───────┘└───────┘└───────┘ ├─│ElectricEngine│
│ └──────────────┘
│ ┌──────────────┐
└─│ HybridEngine │
└──────────────┘
- 如上图,RefinedCar有Engine接口的引用
- 要新增一种品牌的car,只需要新增一个RefinedCar的实现
- 要新增一种引擎,只要新增一种Engine的接口实现
组合Composite
- 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
- 组合模式(Composite)经常用于树形结构,为了简化代码,使用Composite可以把一个叶子节点与一个父节点统一起来处理。
装饰器Decorator
动态地给对象增加一些别的额外职责
- 优点:
- 在不改变原有代码的情况下,把类的核心功能和装饰功能区分开了,并能动态扩展一个对象的新功能
- 有效将类的核心职责和装饰功能让分离开来,也可以去除相关类中重复的装饰逻辑
缺点:
如果客户端要跟许多子系统打交道,那么客户端需要了解各个子系统的接口,比较麻烦。
- 如果有一个统一的“中介”,让客户端只跟中介打交道,中介再去跟各个子系统打交道,对客户端来说就比较简单。所以Facade就相当于搞了一个中介。
享元Flyweight
- 运用共享技术有效地支持大量细粒度的对象。
- 如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。
- 享元模式的设计思想是尽量复用已创建的对象,常用于工厂方法内部的优化。
- Integer.valueOf(12) 很有可能不会新建一个对象,而是返回内存中已经存在的Integer实例(在-128到127之间的int值,都会被缓存)
代理
- 为其他对象提供一种代理以控制对这个对象的访问。
- 与Adapter类似,都是B类持有一个A对象
- 但是这里的代理B类,实现的还是a方法
- 代理模式通过封装一个已有接口,并向调用方返回相同的接口类型,能让调用方在不改变任何代码的前提下增强某些功能(例如,鉴权、延迟加载、连接池复用等)。
- 使用Proxy模式要求调用方持有接口,作为Proxy的类也必须实现相同的接口类型。
- 使用代理模式,实现连接池,close时,不真正关闭连接