设计模式总览
1. 定义
设计模式(DesignPattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:提高代码的可重用性,让代码更容易被他人理解,保证代码可靠性。设计模式使代码编写真正工程化;
2. 设计模式汇总一览
总共 23 个设计模式: 5 个创建型,7 个结构型,11 个行为型;
2.1 创建型
创建型速记: 单工建原抽
| 模式 | 定义与描述 | 优点 | 缺点 |
|---|---|---|---|
| 单例模式(Singleton) | 保证一个类只有一个实例,并提供一个访问它的全局访问点 | 控制实例数量,节省资源 | 可能引入全局状态,难以扩展和测试 |
| 工厂方法模式(Factory Method) | 定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到了子类。 | 解耦对象创建与使用,支持扩展 | 增加了代码复杂性,需要额外的工厂类 |
| 建造者模式(Builder) | 将一个复杂对象的构建与它的表示相分离,使得同样的构建过程可以创建不同的表示 | 分步构建复杂对象,灵活性高 | 增加了代码量,需要定义多个类 |
| 原型模式(Prototype) | 用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象 | 快速克隆对象,减少创建成本 | 深拷贝可能引发性能问题 |
| 抽象工厂模式(Abstract Factory) | 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类 | 统一管理产品族,保证兼容性 | 增加了代码复杂性,难以支持新类型的产品 |
2.2 结构型
结构型速记: 桥代理组装适配器,享元回家装饰外观
解释:有个姓 桥 的 代理 组 装 适配器,他儿子 享元 拿回家 装饰 外观 去啦
| 模式 | 定义与描述 | 优点 | 缺点 |
|---|---|---|---|
| 桥接模式(Bridge) | 将抽象部分与它的实现部分相分离,使它们可以独立地变化 | 将抽象部分与实现部分解耦,可以独立地进行扩展 | 增加了代码复杂性,需要定义多个类 |
| 代理模式(Proxy) | 为其他对象提供一种代理以控制对这个对象的访问 | 为其他对象提供一种代理,控制对对象的访问,支持延迟加载 | 增加了代码复杂性,可能会降低性能 |
| 组合模式(Composite) | 将对象组合成树形结构以表示部分整体的关系,使得用户对单个对象和组合对象的使用具有一致性 | 将对象组合成树形结构,统一处理单个对象和对象集合 | 限制了组合对象的类型,可能导致设计过度 |
| 适配器模式(Adapter) | 将一类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作那些类可以一起工作 | 兼容不兼容接口,复用旧代码 | 增加一层间接性 |
| 享元模式(Flyweight) | 共享大量细粒度对象以节省内存 | 共享细粒度对象,减少内存使用和提高性能 | 增加了代码复杂性,需要维护共享对象的状态 |
| 装饰器模式(Decorator) | 动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator 模式相比生成子类更加灵活 | 动态地给对象添加额外的职责,避免使用子类进行扩展 | 增加了代码复杂性,可能导致过多的装饰器层级 |
| 外观模式(Facade) | 为子系统中的一组接口提供一致的界面,facade 提供了一个高层接口,这个接口使得子系统更容易使用 | 提供了一个简化的接口,隐藏了系统的复杂性 | 可能会违背单一职责原则,导致外观对象过于庞大 |
2.3 行为型
行为型速记: 访问者 写好 策略 备忘录,观察 模板 迭代 的 状态,命令 中介 解释 责任链
解释:这句话讲的就是看房子的经过。
看房子的人就是访问者,看房前要写看房策略和备忘录,不能马马虎虎地去看房子。
去看房子的时候,要仔细观察楼板(模板)层叠(迭代)的状态。
看完房子,命令中介解释清楚产权的责任链。
| 模式 | 定义与描述 | 优点 | 缺点 |
|---|---|---|---|
| 访问者模式(Visitor) | 表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作 | 将数据结构和对数据的操作分离,使得可以在不改变数据结构的前提下定义新的操作 | 新增操作需修改所有访问者 |
| 策略模式(Strategy) | 定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户 | 定义了一系列算法,并将每个算法封装到独立的类中,使得它们可以互相替换。提供了灵活的算法选择和扩展性 | 客户端需了解所有策略 |
| 备忘录模式(Memento) | 在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态 | 在不破坏封装的前提下,捕获并保存对象的内部状态,以便后续恢复 | 增加了代码复杂性,可能会占用大量内存 |
| 观察者模式(Observer) | 定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新 | 定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新 | 可能导致观察者对象过多,难以维护,通知顺序难以控制 |
| 模板方法模式(Template) | 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可以重定义该算法的某些特定步骤 | 定义了一个算法的框架,将具体步骤延迟到子类中实现。提供了一种代码复用和扩展的方式 | 子类的扩展可能会影响算法的整体结构 |
| 迭代器模式(Iterator) | 提供一种方法顺序访问聚合对象中的元素,而不暴露其内部表示 | 提供一种方法顺序访问聚合对象中的元素,而不暴露其内部表示 | 增加了代码复杂性,需要实现迭代器接口 |
| 状态模式(State) | 允许对象在其内部状态改变时改变它的行为。对象看起来似乎改变了它的类 | 状态驱动行为,避免条件判断 | 状态类数量多 |
| 命令模式(Command) | 将请求封装成对象,使得可以用不同的请求对客户进行参数化 | 将请求封装成对象,使得可以用不同的请求对客户进行参数化 | 可能导致命令类的膨胀,增加了代码复杂性 |
| 中介者模式(Mediator) | 用一个中介对象封装一系列的对象交互 | 用一个中介对象来封装一系列对象之间的交互,减少对象之间的直接依赖 | 增加了代码复杂性,中介者对象可能会变得庞大复杂 |
| 解释器模式(Interpreter) | 给定一个语言,定义它的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子 | 定义了一种语言的文法表示,并提供解释器来解释语言中的表达式 | 复杂文法性能差 |
| 责任链模式(Chain) | 使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系 | 将请求的发送者和接收者解耦,通过链式传递请求 | 可能导致请求的处理链过长,难以调试和定位错误,也可能导致请求未被处理 |