新闻详情

新闻详情

首页 / 资讯中心 / 详情

23 种设计模式的通俗解释,虽然有点污

发布时间:2026/9/25 21:43:37来源:尧图网络
23 种设计模式的通俗解释,虽然有点污
一、写在前面设计模式到底在解决什么很多初学者第一次听说“设计模式”时脑子里冒出的画面是厚厚的《GoF 设计模式》原书、满纸的 UML 类图和永远记不住的名字。但说实话设计模式并不是什么高深莫测的咒语它更像是程序员在长期写代码的过程中把反复遇到的“烂摊子”归纳出来的一套套成熟解法。打个比方你装修房子不会每次住新房都重新发明水电布局而是会参考“卫生间干湿分离”“厨房动线三角”这些前人总结的经验。设计模式就是软件工程里的“装修经验”。它们解决的核心问题只有一句话——让代码在面对变化时改起来更轻松、扩展起来更安全、读起来更清晰。这篇文章不打算板着脸讲概念也不会为了博眼球去玩不合适的低俗梗。我会用生活里的小场景来打比方点外卖、找对象、装电脑、搭积木、修水管、订机票。23 个模式一个不落每个都给你一句“人话解释”、一个生活场景、一段关键特点和一份 Java 代码示例。标题里的“有点污”咱们就理解为“有点皮、不太正经”的接地气比喻保证你读完之后下次面试聊设计模式不再只会背“高内聚、低耦合”这一句。二、总览三大阵营一次记牢经典著作《Design Patterns: Elements of Reusable Object-Oriented Software》简称 GoF收录了 23 种设计模式按用途分成三大类分类数量通俗理解包含模式创建型模式5 个解决“对象怎么造出来”的问题单例、工厂方法、抽象工厂、建造者、原型结构型模式7 个解决“类和对象怎么搭起来”的问题适配器、桥接、组合、装饰器、外观、享元、代理行为型模式11 个解决“对象之间怎么沟通协作”的问题责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者记不住没关系先记住一个极简口诀“创建型管生结构型管搭行为型管聊。”下面我们一个模式一个模式地拆开聊。三、创建型模式对象到底怎么“生”出来创建型模式回答的问题是new 一个对象太直接了一旦需求变了直接 new 的地方全要改。于是聪明人想办法把“创建对象”这件事封装起来让调用方不再关心具体 new 的是谁。3.1 单例模式Singleton全公司只有一个老板一句话秒懂保证一个类只有一个实例并提供一个全局访问点。生活场景一家公司的 CEO 只有一个。谁想找 CEO都得通过“董事长办公室”这个唯一入口去找不能随便在大街上 new 一个 CEO 出来。配置类、线程池、数据库连接池、日志管理器这些资源都需要“唯一老大”。如果大家都各自 new 一个配置对象结果配置各读各的整个系统就乱套了。关键点构造方法私有化防止外部 new内部持有唯一实例对外提供静态方法获取实例。它又分“饿汉式”和“懒汉式”两种风格饿汉式像食堂阿姨一早就把菜炒好等你来懒汉式像你饿了自己才打开外卖 App 下单。// 懒汉式 双重检查锁兼顾性能与线程安全 public class ConfigManager { private static volatile ConfigManager instance; private ConfigManager() { // 读取配置文件等初始化操作 } public static ConfigManager getInstance() { if (instance null) { synchronized (ConfigManager.class) { if (instance null) { instance new ConfigManager(); } } } return instance; } }优点节省资源、全局状态统一。缺点全局状态容易被滥用测试时不好替换扩展性一般。3.2 工厂方法模式Factory Method你想吃面不必自己揉面一句话秒懂定义一个创建对象的接口让子类决定实例化哪个类。生活场景你去餐厅说“来碗面”你不会关心后厨是刀削还是手擀。后厨就是“工厂方法”你只需要拿到“面”这个产品。对应到代码父类定义抽象方法createProduct()由不同子类实现返回不同类型的对象。关键点把对象创建的细节下沉到子类调用方只依赖抽象接口。适合在产品类型会扩展、但创建流程统一的场景。// 产品接口 interface Logger { void log(String message); } // 具体产品 class FileLogger implements Logger { public void log(String message) { System.out.println(写入文件 message); } } class ConsoleLogger implements Logger { public void log(String message) { System.out.println(打印控制台 message); } } // 工厂接口 interface LoggerFactory { Logger createLogger(); } // 具体工厂 class FileLoggerFactory implements LoggerFactory { public Logger createLogger() { return new FileLogger(); } } class ConsoleLoggerFactory implements LoggerFactory { public Logger createLogger() { return new ConsoleLogger(); } }优点新增产品时只需加一个工厂子类不用改动已有代码符合开闭原则。缺点类和接口数量变多简单场景下略显繁琐。3.3 抽象工厂模式Abstract Factory一个套餐全家桶一起配齐一句话秒懂提供一个创建一系列相关或相互依赖对象的接口而无需指定它们具体的类。生活场景点“全家桶套餐”一个订单同时给你汉堡、薯条、可乐而且它们必须成套——不能汉堡配个豆浆。抽象工厂就像一个“套餐供应商”能一次性生产出一组配套产品。与工厂方法的区别工厂方法是“只生产一种产品”抽象工厂是“生产一整族配套产品”。例如跨平台的 UI 组件库Windows 风格要同时提供按钮、文本框、下拉框macOS 风格也是同样一套这就是抽象工厂的典型用法。// 同一族的两个产品 interface Button { void render(); } interface Checkbox { void render(); } // 具体族Windows class WindowsButton implements Button { public void render() { System.out.println(渲染 Windows 按钮); } } class WindowsCheckbox implements Checkbox { public void render() { System.out.println(渲染 Windows 复选框); } } // 具体族macOS class MacButton implements Button { public void render() { System.out.println(渲染 macOS 按钮); } } class MacCheckbox implements Checkbox { public void render() { System.out.println(渲染 macOS 复选框); } } // 抽象工厂 interface UIFactory { Button createButton(); Checkbox createCheckbox(); } class WindowsFactory implements UIFactory { public Button createButton() { return new WindowsButton(); } public Checkbox createCheckbox() { return new WindowsCheckbox(); } } class MacFactory implements UIFactory { public Button createButton() { return new MacButton(); } public Checkbox createCheckbox() { return new MacCheckbox(); } }优点保证产品族内对象彼此兼容切换整套实现非常方便。缺点当产品族里要新增一种产品时所有抽象工厂及实现都要改。3.4 建造者模式Builder一步步组装你的豪华电脑一句话秒懂将一个复杂对象的构建与它的表示分离使同样的构建过程可以创建不同的表示。生活场景组装台式机你不可能一个 new 就把 CPU、显卡、内存、硬盘全塞进去。你需要一个“装机单”按步骤先选 CPU再选主板再选显卡最后组装。建造者模式就是这张“装机单”让你可以自由组合参数还可以复用同一套流程造出游戏机或办公机。关键点适合参数特别多、或者对象需要分步骤构造的场景。链条式调用如new Builder().setA().setB().build()可读性非常好。public class Computer { private String cpu; private String gpu; private int memory; private Computer(Builder builder) { this.cpu builder.cpu; this.gpu builder.gpu; this.memory builder.memory; } public static class Builder { private String cpu; private String gpu; private int memory; public Builder cpu(String cpu) { this.cpu cpu; return this; } public Builder gpu(String gpu) { this.gpu gpu; return this; } public Builder memory(int memory) { this.memory memory; return this; } public Computer build() { return new Computer(this); } } } // 使用 Computer pc new Computer.Builder() .cpu(i9) .gpu(RTX 4090) .memory(32) .build();优点链式调用直观、参数可灵活组合、构造过程可控。缺点类结构偏重简单对象用它有点杀鸡用牛刀。3.5 原型模式Prototype复印机原理克隆一个自己一句话秒懂用原型实例指定创建对象的种类并通过拷贝这些原型创建新的对象。生活场景考试前复印资料你不用重新抄一遍直接拿原件放复印机。代码里就是实现clone()尤其是那些创建代价高、初始状态复杂的对象复制比从零构建快得多。关键点Java 中常通过实现Cloneable接口并覆写clone()或者用序列化实现深拷贝。要注意浅拷贝与深拷贝的区别——浅拷贝里引用类型字段还是同一份改一个会影响另一个。public class Report implements Cloneable { private String title; private String content; public Report(String title, String content) { this.title title; this.content content; } Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } // 使用基于模板快速复制出一份新报告再修改 Report template new Report(周报模板, 本周工作总结……); Report copy (Report) template.clone();优点避免重复初始化开销适合克隆复杂对象。缺点深浅拷贝容易踩坑克隆复杂嵌套结构时逻辑复杂。四、结构型模式类和对象到底怎么“搭”起来创建型模式解决了“怎么造”结构型模式解决的是“怎么组合”。很多时候单个类没问题但类一多关系就乱。结构型模式就是教你把类和对象搭成稳定、灵活、可扩展的脚手架。4.1 适配器模式Adapter出国旅游的万能转换插头一句话秒懂把一个类的接口转换成客户端期望的另一个接口让原本不兼容的类能一起工作。生活场景国内的三脚插头到了欧洲插座插不进去。怎么办带一个转换插头。适配器就是那个转换插头把“源插头”变成“目标插座”能接受的样子。在代码里常见于对接第三方库对方的方法名、参数顺序跟我们的系统规范不一致包一层适配器就能无痛对接。// 已有的、但接口不符合要求的类 class LegacyPayment { public void payWithLegacy(String account, double money) { System.out.println(旧系统支付 account 金额 money); } } // 我们系统期望的接口 interface PaymentService { void pay(String userId, double amount); } // 适配器把 LegacyPayment 包装成 PaymentService class PaymentAdapter implements PaymentService { private LegacyPayment legacyPayment new LegacyPayment(); public void pay(String userId, double amount) { legacyPayment.payWithLegacy(userId, amount); } }优点让老代码和新接口共存不动原有实现。缺点适配器太多会让系统层次增多、略显绕。4.2 桥接模式Bridge遥控器和电视各换各的一句话秒懂将抽象部分与实现部分分离使它们可以独立变化。生活场景遥控器抽象和电视实现是两码事。你可以换遥控器也可以换电视两者通过“红外信号”这个桥连接。如果每换一个电视就要写一个新遥控器类会爆炸。桥接模式让它们各变各的互不拖累。关键点避免“多维度变化”带来的类爆炸。例如颜色和形状两个维度如果继承组合写死红色圆形、红色方形、蓝色圆形、蓝色方形就要四个类用桥接只要两个维度各两个类任意组合。// 实现维度 interface Device { void turnOn(); void turnOff(); } class Tv implements Device { public void turnOn() { System.out.println(电视开机); } public void turnOff() { System.out.println(电视关机); } } class Radio implements Device { public void turnOn() { System.out.println(收音机开机); } public void turnOff() { System.out.println(收音机关机); } } // 抽象维度 abstract class RemoteControl { protected Device device; public RemoteControl(Device device) { this.device device; } public abstract void power(); } class BasicRemote extends RemoteControl { public BasicRemote(Device device) { super(device); } public void power() { device.turnOn(); } }优点抽象与实现解耦两个维度独立扩展。缺点引入抽象层次设计门槛稍高场景简单时显得过度设计。4.3 组合模式Composite文件夹里套文件夹一句话秒懂将对象组合成树形结构以表示“部分-整体”的层次结构让客户端可以统一处理单个对象和组合对象。生活场景电脑里的文件夹。文件夹里可以有文件也可以有文件夹文件夹里还能有文件夹。你想统计总大小、删除整个目录不需要区分“当前是文件还是文件夹”一层层递归处理即可。这就是组合模式。关键点定义一个统一的组件接口叶子节点和容器节点都实现它。菜单系统、组织架构、文件系统都是典型场景。import java.util.ArrayList; import java.util.List; interface Node { void print(); } class FileNode implements Node { private String name; public FileNode(String name) { this.name name; } public void print() { System.out.println(文件 name); } } class FolderNode implements Node { private String name; private ListNode children new ArrayList(); public FolderNode(String name) { this.name name; } public void add(Node node) { children.add(node); } public void print() { System.out.println(文件夹 name); for (Node child : children) { child.print(); } } }优点客户端统一处理单体和整体易于递归扩展。缺点叶子和容器都用同一接口设计时可能牺牲一些类型安全性。4.4 装饰器模式Decorator给咖啡加糖、加奶、加冰一句话秒懂动态地给一个对象添加额外的职责而不改变其结构。生活场景你点一杯美式咖啡但想要加糖、加奶、加冰。总不能为“美式加糖”“美式加奶”“美式加糖加奶”各自建一个类吧装饰器模式像一个“配料台”以基础咖啡为核心一层层往上套配料每一层都“装饰”了原来的对象。关键点装饰器与目标对象实现同一接口装饰器内部持有一个被装饰对象的引用在调用原方法前后追加行为。Java 的 IO 流BufferedInputStream包装FileInputStream就是经典案例。interface Coffee { String getDescription(); double cost(); } class SimpleCoffee implements Coffee { public String getDescription() { return 美式咖啡; } public double cost() { return 10.0; } } abstract class CoffeeDecorator implements Coffee { protected Coffee coffee; public CoffeeDecorator(Coffee coffee) { this.coffee coffee; } } class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee coffee) { super(coffee); } public String getDescription() { return coffee.getDescription() 牛奶; } public double cost() { return coffee.cost() 3.0; } } class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee coffee) { super(coffee); } public String getDescription() { return coffee.getDescription() 糖; } public double cost() { return coffee.cost() 1.0; } }优点比继承更灵活可以任意组合职责。缺点装饰层次多的时候会产生很多小对象排查问题略费劲。4.5 外观模式Facade一键启动的总开关一句话秒懂为子系统中的一组接口提供一个统一的高层接口简化调用。生活场景家庭影院有一堆设备——投影仪、音响、蓝光机、幕布。看电影要一步步开太麻烦。于是你装了个中控面板按一下“看电影”它自动把该开的全开了。外观模式就是那个“一键总开关”。关键点不改变子系统本身只提供一个简单的统一入口。常用于给复杂第三方库或旧系统做“门面”降低外部使用成本。class Projector { public void on() { System.out.println(投影仪开启); } } class SoundSystem { public void on() { System.out.println(音响开启); } } class BluRayPlayer { public void on() { System.out.println(蓝光机开启); } } class HomeTheaterFacade { private Projector projector new Projector(); private SoundSystem sound new SoundSystem(); private BluRayPlayer player new BluRayPlayer(); public void watchMovie() { projector.on(); sound.on(); player.on(); System.out.println(开始播放电影); } }优点隔离复杂性调用方与子系统解耦。缺点门面可能变成“上帝对象”承担过多职责。4.6 享元模式Flyweight共享单车而不是人手一辆一句话秒懂运用共享技术有效支持大量细粒度对象减少内存占用。生活场景共享单车。全城几万人在骑车但不需要一人买一辆大家共用一批车即可。代码里如果某个对象内部状态相同、外部状态可变就可以把不变的部分抽出来共享。比如文本编辑器里每个字符都创建一个对象太浪费可以让同一个字符“a”共享一个对象。关键点区分“内部状态”可共享和“外部状态”因人而异。典型应用有字符串常量池、数据库连接池、围棋棋盘棋子。import java.util.HashMap; import java.util.Map; class CharacterStyle { private final String font; private final int size; public CharacterStyle(String font, int size) { this.font font; this.size size; } Override public boolean equals(Object o) { /* 省略判断逻辑 */ return false; } Override public int hashCode() { return (font size).hashCode(); } } class StyleFactory { private static final MapString, CharacterStyle pool new HashMap(); public static CharacterStyle getStyle(String font, int size) { String key font - size; return pool.computeIfAbsent(key, k - new CharacterStyle(font, size)); } }优点大幅减少对象数量节省内存。缺点引入共享逻辑内部外部状态划分不好会变复杂。4.7 代理模式Proxy经纪人替明星谈合作一句话秒懂为其他对象提供一种代理以控制对这个对象的访问。生活场景大明星很忙谈广告合作先找经纪人。经纪人代理可以过滤合作请求、签合同细节最后需要时再转达给明星。代码里的代理对象和被代理对象实现同一接口客户端感知不到区别但代理可以在前后加权限校验、日志、缓存、延迟加载等逻辑。关键点有静态代理和动态代理。Spring AOP 的底层大量依赖动态代理技术。典型场景还包括远程代理、虚拟代理、保护代理。interface Image { void display(); } class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename filename; loadFromDisk(); } private void loadFromDisk() { System.out.println(从磁盘加载 filename); } public void display() { System.out.println(显示图片 filename); } } class ImageProxy implements Image { private RealImage realImage; private String filename; public ImageProxy(String filename) { this.filename filename; } public void display() { if (realImage null) { realImage new RealImage(filename); // 延迟到真正使用时才加载 } realImage.display(); } }优点职责清晰能透明地增强控制。缺点增加一层间接性可能降低部分性能。五、行为型模式对象之间到底怎么“协作”行为型模式关注的是对象之间的责任分配和算法封装本质是让“变化的行为”可以被灵活替换、传递和复用而不是把各种 if/else 堆在业务代码里。5.1 责任链模式Chain of Responsibility层层审批能搞定就办一句话秒懂使多个对象都有机会处理请求将这些对象连成一条链请求沿链传递直到被处理。生活场景报销单要审批。500 元以内部门经理批500 到 5000 元总监批5000 元以上总经理批。报销单从经理开始传递谁权限够谁处理不够就向上抛。代码里把多个处理器串成链表每个处理器判断“这事我能不能管”。关键点解耦请求发送者和接收者职责清晰、可动态调整链条顺序。常见于网关过滤器、日志级别处理。abstract class Approver { protected Approver next; public void setNext(Approver next) { this.next next; } public abstract void approve(int amount); } class Manager extends Approver { public void approve(int amount) { if (amount 500) { System.out.println(经理审批通过 amount); } else if (next ! null) { next.approve(amount); } } } class Director extends Approver { public void approve(int amount) { if (amount 5000) { System.out.println(总监审批通过 amount); } else if (next ! null) { next.approve(amount); } } } class GeneralManager extends Approver { public void approve(int amount) { System.out.println(总经理终审通过 amount); } }优点灵活分配职责新增处理者不影响现有链。缺点链太长影响性能也可能出现请求无人处理的遗漏。5.2 命令模式Command餐厅点单服务员和厨师的契约一句话秒懂把请求封装成对象从而可以用不同的请求、队列、日志来参数化其他对象。生活场景你点菜不需要跑到后厨喊而是把需求写在“点菜单”上交给服务员。点菜单就是命令对象服务员负责传递厨师负责执行。这样还可以排队、撤销、记录日志。关键点命令的发起者与执行者解耦命令可以被排队、撤销、重做、持久化。典型场景有任务队列、撤销操作、宏命令。// 接收者 class Light { public void on() { System.out.println(开灯); } public void off() { System.out.println(关灯); } } // 命令接口 interface Command { void execute(); void undo(); } class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light light; } public void execute() { light.on(); } public void undo() { light.off(); } } // 调用者 class RemoteInvoker { private Command command; public void setCommand(Command command) { this.command command; } public void pressButton() { command.execute(); } }优点支持撤销/重做调用者与执行者解耦。缺点类和对象数量增加简单操作显得繁琐。5.3 解释器模式Interpreter像翻译一句话那样解析规则一句话秒懂给定一种语言定义它的文法表示并定义一个解释器来解释句子。生活场景你教小孩“1 加 2 等于几”先要让他理解“加”这个符号的含义再逐个解释表达式。代码里常用于解析特定的小型语法比如规则引擎里的条件表达式、简单的数学表达式计算器。关键点把文法中的每个符号对应到一个解释器类递归组合解释。适合语法简单、稳定且执行频率不高的场景。复杂语法建议用现成的解析器而不是手写解释器。interface Expression { int interpret(); } class NumberExpression implements Expression { private int number; public NumberExpression(int number) { this.number number; } public int interpret() { return number; } } class AddExpression implements Expression { private Expression left; private Expression right; public AddExpression(Expression left, Expression right) { this.left left; this.right right; } public int interpret() { return left.interpret() right.interpret(); } } // 解析 1 2 Expression expr new AddExpression( new NumberExpression(1), new NumberExpression(2) ); int result expr.interpret(); // result 3优点规则表达清晰易于扩展新的语法规则。缺点复杂文法会产生大量类维护成本高。5.4 迭代器模式Iterator统一的方式遍历各种集合一句话秒懂提供一种方法顺序访问聚合对象中的各个元素而又不暴露其内部表示。生活场景你去图书馆找书不管书架是竖排、横排还是旋转式的你都希望有个统一的“浏览顺序”。迭代器让你不需要关心集合底层是数组、链表还是树统一用next()一步步访问。关键点把遍历逻辑从集合中抽离支持多种遍历方式。Java 的Iterator、for-each语法糖都基于此。import java.util.Iterator; import java.util.List; import java.util.ArrayList; public class IteratorDemo { public static void main(String[] args) { ListString names new ArrayList(); names.add(张三); names.add(李四); names.add(王五); IteratorString it names.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }优点隐藏内部实现统一遍历接口。缺点简单集合直接用已有迭代器即可自己实现的机会较少。5.5 中介者模式Mediator群聊加个群主统一协调一句话秒懂用一个中介对象封装一系列对象之间的交互使各对象之间不必显式地相互引用。生活场景一个群里几十个人如果每两人都要私聊关系网密得可怕。有了群主中介者大家把消息发给群主群主统一分发。代码里多个组件之间网状通信改成星状通信组件只依赖中介者。关键点减少对象间耦合。适合交互复杂的系统如聊天室、机场调度塔台。缺点是中介者本身可能膨胀成复杂的大类。import java.util.ArrayList; import java.util.List; interface ChatMediator { void sendMessage(String message, User sender); } class ChatRoom implements ChatMediator { private ListUser users new ArrayList(); public void addUser(User user) { users.add(user); } public void sendMessage(String message, User sender) { for (User user : users) { if (user ! sender) { user.receive(message); } } } } class User { private String name; private ChatMediator mediator; public User(String name, ChatMediator mediator) { this.name name; this.mediator mediator; } public void send(String message) { mediator.sendMessage(message, this); } public void receive(String message) { System.out.println(name 收到 message); } }优点大幅降低对象间耦合交互集中管理。缺点中介者可能变成复杂臃肿的“超级类”。5.6 备忘录模式Memento游戏的存档与读档一句话秒懂在不破坏封装的前提下捕获一个对象的内部状态并在之后将对象恢复到该状态。生活场景打 RPG 游戏打到大 Boss 前先存个档死了就读档重来。存档就是备忘录记录了当时的血量、金币、关卡。代码里把对象状态快照保存起来需要时恢复且不暴露内部细节。关键点常用于编辑器撤销、事务回滚。要控制好快照的内存占用只保存必要状态。class GameState { private int level; private int hp; public GameState(int level, int hp) { this.level level; this.hp hp; } public int getLevel() { return level; } public int getHp() { return hp; } } class Game { private int level; private int hp; public void play(int deltaHp) { hp deltaHp; } public GameState save() { return new GameState(level, hp); } public void restore(GameState state) { this.level state.getLevel(); this.hp state.getHp(); } }优点状态快照可保存与恢复封装性好。缺点大对象快照可能占用大量内存。5.7 观察者模式Observer公众号推送订阅了就收一句话秒懂定义对象间一对多的依赖关系当一个对象状态改变时所有依赖它的对象都得到通知并自动更新。生活场景你关注了一个公众号它一发文你就收到推送。你不关注就不打扰你。发布者Subject维护订阅者列表状态变化时逐一通知。这是消息推送、事件驱动的基础模型。关键点发布者与订阅者解耦新增订阅者无需改动发布者。Java 早期的Observable/Observer已被更灵活的事件机制取代。import java.util.ArrayList; import java.util.List; // 订阅者接口 interface Subscriber { void update(String news); } // 发布者 class NewsPublisher { private ListSubscriber subscribers new ArrayList(); public void subscribe(Subscriber subscriber) { subscribers.add(subscriber); } public void unsubscribe(Subscriber subscriber) { subscribers.remove(subscriber); } public void publish(String news) { for (Subscriber subscriber : subscribers) { subscriber.update(news); } } } class UserSubscriber implements Subscriber { private String name; public UserSubscriber(String name) { this.name name; } public void update(String news) { System.out.println(name 收到消息 news); } }优点对象间松耦合广播通知便捷。缺点通知顺序不可控订阅者太多时可能出现性能问题。5.8 状态模式State自动售货机的不同状态一句话秒懂允许对象在其内部状态改变时改变它的行为看起来好像修改了它的类。生活场景自动售货机有“有货”“无货”“投币中”等状态。同样是按“出货”按钮有货时出货无货时退款提示。如果不拆状态就要写一大堆 if/else。状态模式把每个状态封装成类状态转换时切换行为。关键点消除冗长的条件判断使状态转换清晰。适合订单状态流转、游戏角色状态等场景。interface VendingState { void insertCoin(VendingMachine machine); void dispense(VendingMachine machine); } class NoStockState implements VendingState { public void insertCoin(VendingMachine machine) { System.out.println(无货请勿投币); } public void dispense(VendingMachine machine) { System.out.println(无货可出); } } class HasStockState implements VendingState { public void insertCoin(VendingMachine machine) { System.out.println(已投币准备出货); } public void dispense(VendingMachine machine) { System.out.println(出货成功); } } class VendingMachine { private VendingState state; public void setState(VendingState state) { this.state state; } public void insertCoin() { state.insertCoin(this); } public void dispense() { state.dispense(this); } }优点状态逻辑清晰、易于扩展新状态。缺点状态类数量增多状态较少时反而复杂。5.9 策略模式Strategy出门带哪把伞看天气再决定一句话秒懂定义一系列算法把它们封装起来并使它们可以相互替换。生活场景出门前看天气——下雨带雨伞大太阳带遮阳伞下雪带雪地装备。你不需要把三种装备都背上出门时选一种“策略”即可。代码里不同算法各自封装成类客户端可任意切换。关键点策略模式与状态模式结构相似但意图不同策略是客户端主动切换算法状态是对象内部状态驱动行为变化。常用于多支付渠道、多排序算法、多优惠规则。interface SortStrategy { void sort(int[] array); } class BubbleSort implements SortStrategy { public void sort(int[] array) { System.out.println(使用冒泡排序); } } class QuickSort implements SortStrategy { public void sort(int[] array) { System.out.println(使用快速排序); } } class Sorter { private SortStrategy strategy; public void setStrategy(SortStrategy strategy) { this.strategy strategy; } public void sort(int[] array) { strategy.sort(array); } }优点算法可自由替换去除条件分支。缺点策略类变多需要客户端理解各策略差异。5.10 模板方法模式Template Method泡茶和冲咖啡套路一样一句话秒懂定义算法的骨架将一些步骤延迟到子类实现。生活场景泡茶和冲咖啡流程惊人相似烧水、放原料、冲泡、加调料。只是“放原料”“加调料”不同。模板方法把固定流程写在父类变化的步骤留给子类。关键点固定不变的流程放父类钩子方法让子类定制。适合框架搭建如 JDBC 的查询流程、Servlet 生命周期。abstract class BeverageMaker { // 模板方法final 防止子类修改流程 public final void makeBeverage() { boilWater(); brew(); pourInCup(); addCondiments(); } private void boilWater() { System.out.println(烧水); } private void pourInCup() { System.out.println(倒入杯子); } // 由子类实现的步骤 protected abstract void brew(); protected abstract void addCondiments(); } class TeaMaker extends BeverageMaker { protected void brew() { System.out.println(泡茶叶); } protected void addCondiments() { System.out.println(加柠檬); } }优点复用骨架、规范流程、子类只关注差异。缺点扩展受父类固定流程限制可能违背里氏替换原则。5.11 访问者模式Visitor审计员来检查不同部门一句话秒懂将数据操作与数据结构分离在不修改数据结构的情况下添加新的操作。生活场景审计员去不同部门检查。财务部、技术部、销售部的报表格式不同审计员需要分别处理。如果把检查逻辑写进各部门以后每来一个新审计员就要改所有部门访问者模式反过来让“访问者”带着操作逻辑去访问“元素”。关键点适合对象结构稳定、但需要频繁新增操作的场景。典型应用是编译器语法树检查、电商报表统计。缺点是元素结构变化时所有访问者都要改。// 元素接口 interface Element { void accept(Visitor visitor); } class Book implements Element { public void accept(Visitor visitor) { visitor.visitBook(this); } } class Fruit implements Element { public void accept(Visitor visitor) { visitor.visitFruit(this); } } // 访问者接口 interface Visitor { void visitBook(Book book); void visitFruit(Fruit fruit); } class PriceVisitor implements Visitor { public void visitBook(Book book) { System.out.println(书本计价); } public void visitFruit(Fruit fruit) { System.out.println(水果称重计价); } }优点新增操作方便业务操作与数据结构分离。缺点结构变化时影响面大且访问者需要了解元素细节破坏一定封装。六、总结23 个模式怎样才算真正学会读到这里你会发现 23 个模式各有分工但底层只有两个核心思想一是面向接口编程二是把变化封装起来。创建型模式封装“创建的变化”结构型模式封装“组合的变化”行为型模式封装“交互的变化”。学习设计模式最容易掉进两个坑第一个坑是死记硬背。只背名字、背类图不动手写遇到真实问题还是不会用。建议每个模式至少手写一遍最简版本再思考“如果不用这个模式代码会烂在哪”。第二个坑是过度设计。为了用模式而用模式结果一个本来 50 行能搞定的功能硬是堆了十几个类和接口。记住一句话模式是手段简单可维护才是目的。当代码已经清晰、够用、不容易出错时不套模式也是一种选择。最后给一个理解框架帮你快速回忆问题答案模式对象只能有一个单例对象创建太多分支工厂方法、抽象工厂对象参数多、构建复杂建造者创建成本高、想复制原型接口对不上适配器两个维度独立变化桥接整体与部分一致处理组合动态叠加职责装饰器简化复杂子系统外观海量对象共享享元访问控制与增强代理请求逐级传递责任链请求封装与撤销命令解析表达式/规则解释器统一遍历集合迭代器多方协调通信中介者保存恢复状态备忘录一对多通知观察者状态切换行为状态算法可替换策略固定流程留钩子模板方法结构与操作分离访问者把这篇文章收藏起来下次写代码卡壳时先问自己一句“我现在遇到的是‘创建’的问题、‘结构’的问题还是‘行为’的问题”答案一出模式自然就浮现了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

FDE 实战:给 AI 加上 Tool Calling,让模型真正操作业务系统 2026/9/25 22:19:17

FDE 实战:给 AI 加上 Tool Calling,让模型真正操作业务系统

FDE 实战:给 AI 加上 Tool Calling,让模型真正操作业务系统 专栏:《AI FDE 实战:从 Demo 到生产》|第 11 篇 / 共 18 篇 本篇目标:让模型通过受控工具查询订单、形成工单草稿,并由独立的人工确认…

阅读更多 →
Mate XT 2 不再只有折叠、半折、展开:九种形态怎么建成可维护状态机 2026/9/25 22:18:12

Mate XT 2 不再只有折叠、半折、展开:九种形态怎么建成可维护状态机

Mate XT 2 不再只有折叠、半折、展开:九种形态怎么建成可维护状态机 应用在 Mate XT 上只处理“折叠、半折、展开”还能工作,换到 Mate XT 2 后却出现左屏折叠、右屏展开时仍套用三屏布局。最新三折叠指南明确指出:两个铰链各自都有折叠、半…

阅读更多 →
2025 AI出海实战:算力选型、大模型部署与Agent落地关键节点 2026/9/25 22:17:45

2025 AI出海实战:算力选型、大模型部署与Agent落地关键节点

1. 算力格局变了,出海的起跑线也跟着变了2025年做AI出海,如果还拿2023年那套“国内训模型、海外套个壳”的思路来打,基本等于开局就落后半个身位。我过去一年跟几个做多模态和Agent方向的团队聊下来,最直观的感受是:算…

阅读更多 →
从自研RAG到WeKnora:企业知识库落地全记录 2026/9/25 22:17:45

从自研RAG到WeKnora:企业知识库落地全记录

去年年初我们团队接了一个内部知识库的项目,要求把几十万份产品文档、故障工单和技术规范变成可检索、可问答的资产。一开始我们天真地以为“接个大模型API就完事了”,结果两个月下来,最耗精力的根本不是模型本身,而是围绕知识接入…

阅读更多 →
Atlas 300V 24G推理加速卡跑YOLO:从环境搭建到模型转换全攻略 2026/9/25 22:17:45

Atlas 300V 24G推理加速卡跑YOLO:从环境搭建到模型转换全攻略

看到“atlas 300v 24g 是运算加速卡吗”这个问题,我第一反应是,又有人要入坑 AI 推理这条线了。先给结论:Atlas 300V 24G 确实是一张运算加速卡,但它不是普通显卡,更不是用来打游戏的,它是一张专门为神经网…

阅读更多 →
后端人别再焦虑了!核心能力其实就这些 2026/9/25 22:17:31

后端人别再焦虑了!核心能力其实就这些

打开技术社区,满屏都是“Spring Cloud Alibaba实战”“Service Mesh落地”“云原生架构演进”,再刷刷招聘要求,分布式、高并发、微服务、容器化、DDD……仿佛少学一样就会被时代抛弃。于是很多后端人陷入焦虑:新技术层出不穷&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉