一、概述
这里推荐阅读两本书:《设计模式:可复用面向对象软件的基础》和《大话设计模式》。
前者推荐那些能啃的下硬骨头的人去读(太过于严谨枯燥,毕竟是学术派书籍),后者则推荐所有想要了解设计模式的人去读(后者有烂代码和好代码的对比,且其所有伪代码的实现都更贴近生活和业务要求,容易理解)。
对于23种常见设计模式的分类:
二、总结
关于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)
生活案例:自定义计算器。
作用:定义语言的文法并解释执行。
评论