一、概述

这里推荐阅读两本书:《设计模式:可复用面向对象软件的基础》《大话设计模式》

前者推荐那些能啃的下硬骨头的人去读(太过于严谨枯燥,毕竟是学术派书籍),后者则推荐所有想要了解设计模式的人去读(后者有烂代码和好代码的对比,且其所有伪代码的实现都更贴近生活和业务要求,容易理解)。

对于23种常见设计模式的分类:

分类

核心关注点

包含的模式 (共23种)

创建型
(5种)

对象怎么创建;
隐藏创建逻辑,解耦对象的创建与使用。

单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。

结构型

(7种)

类/对象怎么组合;
将类或对象组合成更大的结构,简化关系。

适配器模式、装饰器模式、代理模式、外观模式、组合模式、桥接模式、享元模式。

行为型

(11种)

对象怎么交互;
分配职责,管理对象间的通信和算法。

观察者模式、策略模式、模板方法模式、责任链模式、命令模式、状态模式、迭代器模式、中介者模式、备忘录模式、访问者模式、解释器模式。

二、总结

关于23种常见设计模式的总结:

创建型模式 (Creational Patterns)

核心目标:把对象的“创建过程”和“使用过程”分离开,让系统更灵活。

1. 单例模式 (Singleton)

  • 生活案例:全公司只有一台打印机,或者一个班级只有一个班主任。

  • 作用:保证一个类只有一个实例,并提供一个全局访问点。

  • 场景:数据库连接池、配置文件读取器、日志对象。

2. 工厂方法模式 (Factory Method)

  • 生活案例:你去奶茶店点单,你只需要说“我要一杯奶茶”,具体的制作是由店里的员工(工厂)完成的,你不需要知道奶茶是怎么做出来的。

  • 作用:定义一个创建对象的接口,但让子类决定实例化哪个类。

  • 场景:日志记录器(根据配置创建文件日志或数据库日志)。

3. 抽象工厂模式 (Abstract Factory)

  • 生活案例:小米生态链。你买一套“小米智能家居”,里面包含了小米的手机、小米的电视、小米的路由器。它们是一套相关的系列产品。

  • 作用:提供一个接口,用于创建相关或依赖的一系列对象(产品族),而无需指定具体类。

  • 场景:换肤功能(一套UI主题包含按钮、窗口、边框等多种控件)。

4. 建造者模式 (Builder)

  • 生活案例:点外卖套餐。你可以一步步选择:主食选汉堡,配菜选薯条,饮料选可乐。最后组装成一个完整的套餐。

  • 作用:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  • 场景:构建复杂的SQL语句、生成复杂的报表对象。

5. 原型模式 (Prototype)

  • 生活案例:Word文档的“另存为”。你基于一个现有的模板文件,复制一份出来修改,而不是从头新建。

  • 作用:通过复制(克隆)现有实例来创建新对象。

  • 场景:对象创建成本较高(如读取大文件),且新对象与旧对象结构相似时。


结构型模式 (Structural Patterns)

核心目标:像搭积木一样,将类或对象组合起来,形成更大、更稳定的结构。

1. 适配器模式 (Adapter)

  • 生活案例:USB转接头。你的电脑只有USB-C接口,但鼠标是USB-A接口,中间加个转接头就能用了。

  • 作用:将一个类的接口转换成客户期望的另一个接口,解决接口不兼容问题。

  • 场景:整合旧系统代码、数据格式转换。

2. 装饰器模式 (Decorator)

  • 生活案例:奶茶加料。基础是原味奶茶,你可以动态地加珍珠、加椰果、加布丁。每加一种料,功能(口感/价格)就增加一点。

  • 作用:动态地给对象添加额外的职责,比继承更灵活。

  • 场景:Java IO流(new BufferedInputStream(new FileInputStream(...)))、函数装饰器。

3. 代理模式 (Proxy)

  • 生活案例:明星经纪人。你想找明星演出,不能直接找明星,必须通过经纪人。经纪人可以控制访问(比如检查你的预算、安排时间)。

  • 作用:为另一个对象提供一个代理或占位符,以控制对它的访问。

  • 场景:远程代理(RPC调用)、虚拟代理(图片懒加载)、保护代理(权限控制)。

4. 外观模式 (Facade)

  • 生活案例:一键启动。开车时,你只需要按一个“启动键”,不需要先去开油泵、再点火、再开空调。这个按钮就是外观。

  • 作用:为复杂的子系统提供一个统一的、简化的接口。

  • 场景:框架的入口类、封装复杂的第三方SDK调用。

5. 组合模式 (Composite)

  • 生活案例:文件夹。文件夹里可以放文件,也可以放子文件夹。你对“文件夹”执行删除操作,里面的所有内容都会被删除。

  • 作用:将对象组合成树形结构以表示“部分-整体”的层次结构,让用户对单个对象和组合对象的使用具有一致性。

  • 场景:UI组件树(Window包含Panel,Panel包含Button)、文件系统。

6. 桥接模式 (Bridge)

  • 生活案例:遥控器与电视。遥控器(抽象)和电视(实现)是分离的。你可以用小米遥控器控制索尼电视,只要接口匹配。它们可以独立变化。

  • 作用:将抽象部分与实现部分分离,使它们都可以独立变化。

  • 场景:不同数据库驱动、不同操作系统的UI绘制。

7. 享元模式 (Flyweight)

  • 生活案例:五子棋。棋盘上有许多黑子和白子,但内存中只需要两个棋子对象(一个黑、一个白),通过共享位置坐标来显示。

  • 作用:运用共享技术来有效地支持大量细粒度的对象,减少内存占用。

  • 场景:文本编辑器中的字符对象、游戏地图中的树木/草地模型。


行为型模式 (Behavioral Patterns)

核心目标:关注对象之间的通信、职责分配以及算法的封装。

1. 观察者模式 (Observer)

  • 生活案例:B站关注。UP主(被观察者)发了新视频,所有关注他的粉丝(观察者)都会收到通知。

  • 作用:定义对象间的一种一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。

  • 场景:事件驱动系统、消息队列、MVVM框架的数据绑定。

2. 策略模式 (Strategy)

  • 生活案例:导航软件。从A到B,你可以选择“驾车”、“步行”或“骑行”策略。不同的策略对应不同的路线算法,可以随时切换。

  • 作用:定义一系列算法,将它们封装起来,并使它们可以相互替换。

  • 场景:支付渠道切换(微信/支付宝)、压缩算法选择(Zip/Rar)。

3. 模板方法模式 (Template Method)

  • 生活案例:做菜流程。做“红烧肉”和“红烧鱼”流程类似:热油 -> 煎食材 -> 加调料 -> 出锅。流程框架固定,具体煎什么食材由子类决定。

  • 作用:定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。

  • 场景:框架生命周期钩子(如Django/Flask的请求处理流程)、SOP标准化流程。

4. 责任链模式 (Chain of Responsibility)

  • 生活案例:请假审批。请假3天找组长,3-7天找经理,7天以上找CTO。请求沿着链条传递,直到有人处理。

  • 作用:使多个对象都有机会处理请求,从而解除请求发送者和接收者之间的耦合。

  • 场景:OA审批流、Web框架的中间件(Middleware)、异常处理。

5. 命令模式 (Command)

  • 生活案例:餐厅点单。服务员把顾客的要求(命令)写在单子上,厨师根据单子做菜。这使得支持“撤销”或“排队”变得容易。

  • 作用:将请求封装成对象,从而支持撤销、重做、排队等操作。

  • 场景:GUI按钮点击事件、任务队列、宏命令。

6. 状态模式 (State)

  • 生活案例:手机模式。手机在“静音模式”下,来电不响铃;在“正常模式”下,来电响铃。手机内部状态改变,其行为也随之改变。

  • 作用:允许一个对象在其内部状态改变时改变它的行为。

  • 场景:订单状态流转(待支付->已发货->已完成)、TCP连接状态。

7. 迭代器模式 (Iterator)

  • 作用:提供一种方法顺序访问集合中的元素,而不暴露内部结构(如Python的for x in list,enumerate...)。

8. 中介者模式 (Mediator)

  • 生活案例:房产中介。房东和租客不直接联系,通过中介沟通,

  • 作用:减少对象间的直接依赖。

9. 备忘录模式 (Memento)

  • 生活案例:游戏存档。

  • 作用:保存对象在某一时刻的状态,以便后续恢复。

10. 访问者模式 (Visitor)

  • 生活案例:会计师查账。

  • 作用:在不修改数据结构的前提下,对数据元素执行新的操作。

11. 解释器模式 (Interpreter)

  • 生活案例:自定义计算器。

  • 作用:定义语言的文法并解释执行。