设计模式速查表
本文档提供 23 种经典设计模式的快速参考,帮助你快速回顾和查阅。
设计原则速查
SOLID 原则
| 原则 | 名称 | 核心思想 |
|---|---|---|
| S | 单一职责原则 | 一个类只负责一项职责 |
| O | 开闭原则 | 对扩展开放,对修改关闭 |
| L | 里氏替换原则 | 子类可以替换父类 |
| I | 接口隔离原则 | 接口要小而专一 |
| D | 依赖倒置原则 | 依赖抽象而非具体实现 |
其他原则
| 原则 | 核心思想 |
|---|---|
| 迪米特法则 | 最少知识,只与直接朋友通信 |
| 组合复用原则 | 优先组合而非继承 |
| 共同封闭原则 | 一起变化的类放在一起 |
| 稳定依赖原则 | 依赖更稳定的方向 |
创建型模式
模式对比
| 模式 | 目的 | 核心思想 |
|---|---|---|
| 单例 | 唯一实例 | 确保一个类只有一个实例 |
| 工厂方法 | 延迟创建 | 子类决定创建哪个类 |
| 抽象工厂 | 产品族 | 创建相关对象的家族 |
| 建造者 | 复杂对象 | 分步骤构建复杂对象 |
| 原型 | 克隆 | 通过复制创建对象 |
单例模式
// 推荐:枚举实现
public enum Singleton {
INSTANCE;
public void doSomething() { }
}
// 推荐:静态内部类
public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
工厂方法模式
// 产品接口
interface Product { void use(); }
// 工厂接口
interface Factory { Product create(); }
// 具体工厂创建具体产品
class ConcreteFactory implements Factory {
public Product create() { return new ConcreteProduct(); }
}
抽象工厂模式
// 抽象工厂
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 具体工厂创建产品族
class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public Checkbox createCheckbox() { return new WindowsCheckbox(); }
}
建造者模式
// 链式调用构建复杂对象
Product product = Product.builder()
.name("商品名称")
.price(99.9)
.description("商品描述")
.build();
原型模式
// 实现 Cloneable
class Prototype implements Cloneable {
public Prototype clone() {
return (Prototype) super.clone();
}
}
结构型模式
模式对比
| 模式 | 目的 | 核心思想 |
|---|---|---|
| 适配器 | 接口转换 | 将接口转换为客户期望的接口 |
| 桥接 | 分离抽象与实现 | 抽象与实现分离,独立变化 |
| 组合 | 树形结构 | 统一处理单个对象和组合对象 |
| 装饰器 | 动态扩展 | 动态添加职责 |
| 外观 | 简化接口 | 提供统一的高层接口 |
| 享元 | 共享细粒度对象 | 共享公共状态 |
| 代理 | 控制访问 | 控制对象的访问 |
适配器模式
// 对象适配器
class Adapter implements Target {
private Adaptee adaptee;
public void request() {
adaptee.specificRequest(); // 转换调用
}
}
装饰器模式
// 装饰器基类
abstract class Decorator implements Component {
protected Component component;
public void operation() {
component.operation();
}
}
// 具体装饰器
class ConcreteDecorator extends Decorator {
public void operation() {
super.operation();
addedBehavior(); // 添加新行为
}
}
代理模式
// 代理类控制访问
class Proxy implements Subject {
private RealSubject realSubject;
public void request() {
// 前置处理
realSubject.request();
// 后置处理
}
}
组合模式
// 组件接口
interface Component {
void operation();
}
// 叶子节点
class Leaf implements Component {
public void operation() { /* 叶子操作 */ }
}
// 组合节点
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component c) { children.add(c); }
public void operation() {
for (Component c : children) c.operation();
}
}
行为型模式
模式对比
| 模式 | 目的 | 核心思想 |
|---|---|---|
| 策略 | 算法封装 | 可替换的算法族 |
| 观察者 | 依赖通知 | 一对多的依赖关系 |
| 命令 | 请求封装 | 将请求封装成对象 |
| 迭代器 | 遍历聚合 | 顺序访问聚合元素 |
| 模板方法 | 算法骨架 | 定义算法骨架,子类实现细节 |
| 状态 | 状态变化 | 对象行为随状态变化 |
| 责任链 | 请求传递 | 沿链传递请求 |
| 中介者 | 对象交互 | 集中管理对象交互 |
| 备忘录 | 状态保存 | 保存和恢复对象状态 |
| 访问者 | 分离操作 | 分离数据结构与操作 |
策略模式
// 策略接口
interface Strategy { void execute(); }
// 上下文使用策略
class Context {
private Strategy strategy;
public void setStrategy(Strategy s) { this.strategy = s; }
public void execute() { strategy.execute(); }
}
// 使用 lambda 简化
context.setStrategy(() -> System.out.println("策略执行"));
观察者模式
// 观察者接口
interface Observer { void update(String message); }
// 主题
class Subject {
private List<Observer> observers = new ArrayList<>();
public void attach(Observer o) { observers.add(o); }
public void notify(String msg) {
for (Observer o : observers) o.update(msg);
}
}
命令模式
// 命令接口
interface Command { void execute(); }
// 具体命令
class ConcreteCommand implements Command {
private Receiver receiver;
public void execute() { receiver.action(); }
}
// 调用者
class Invoker {
private Command command;
public void setCommand(Command c) { this.command = c; }
public void invoke() { command.execute(); }
}
责任链模式
// 处理者
abstract class Handler {
protected Handler next;
public Handler setNext(Handler h) { this.next = h; return h; }
public abstract void handle(Request request);
}
// 使用链式调用
handler1.setNext(handler2).setNext(handler3);
模板方法模式
// 抽象类定义模板
abstract class AbstractClass {
public final void templateMethod() {
step1();
step2(); // 可被子类覆盖
step3();
}
protected abstract void step2();
}
状态模式
// 状态接口
interface State { void handle(Context context); }
// 上下文
class Context {
private State state;
public void setState(State s) { this.state = s; }
public void request() { state.handle(this); }
}
模式选择指南
根据意图选择
| 意图 | 推荐模式 |
|---|---|
| 创建对象 | 工厂、建造者、原型 |
| 唯一实例 | 单例 |
| 组合对象 | 组合、装饰器 |
| 改变行为 | 策略、状态 |
| 通知变化 | 观察者 |
| 简化接口 | 外观 |
| 解耦 | 中介者、观察者 |
| 延迟操作 | 代理、命令 |
根据问题选择
| 问题 | 推荐模式 |
|---|---|
| 大量 if-else | 策略、状态 |
| 代码重复 | 模板方法 |
| 类数量爆炸 | 享元、代理 |
| 紧耦合 | 依赖注入、观察者 |
| 难以扩展 | 工厂方法、开闭原则 |
常见模式组合
策略 + 工厂
// 工厂创建策略
Strategy strategy = StrategyFactory.create(type);
context.setStrategy(strategy);
观察者 + 单例
// 单例主题
public enum EventBus {
INSTANCE;
private List<Observer> observers = new ArrayList<>();
// ...
}
装饰器 + 建造者
// 建造者创建装饰器
Component component = ComponentBuilder.create()
.withDecoratorA()
.withDecoratorB()
.build();
反模式警示
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 上帝类 | 类职责过多 | 单一职责原则 |
| 复制粘贴编程 | 代码重复 | 模板方法、策略模式 |
| 过度设计 | 不必要的复杂性 | YAGNI 原则 |
| 面条代码 | 逻辑混乱 | 重构、模式应用 |
| 过早优化 | 性能问题假想 | 先保证正确,再优化 |
模式使用频率
高频使用
- 单例模式
- 工厂方法模式
- 策略模式
- 观察者模式
- 适配器模式
- 装饰器模式
中频使用
- 建造者模式
- 代理模式
- 模板方法模式
- 责任链模式
- 组合模式
低频使用
- 原型模式
- 桥接模式
- 享元模式
- 中介者模式
- 访问者模式
- 备忘录模式
重构到模式
重构信号
| 代码异味 | 重构方向 | 推荐模式 |
|---|---|---|
| 大类 | 提取类 | 策略、状态 |
| 长方法 | 提取方法 | 模板方法 |
| 参数列表过长 | 引入参数对象 | 建造者 |
| switch 语句 | 以多态替代 | 策略、状态 |
| 重复代码 | 提取父类 | 模板方法 |
重构步骤
- 识别问题:发现代码异味
- 选择模式:确定合适的模式
- 小步重构:逐步应用模式
- 测试验证:确保功能正确
- 持续优化:根据反馈调整
UML 符号速查
类图符号
| 符号 | 关系 | 说明 |
|---|---|---|
| ──────> | 依赖 | A 依赖 B |
| ─────▷ | 泛化 | A 继承 B |
| ─────▷▷ | 实现 | A 实现 B |
| ◆────── | 组合 | 强拥有关系 |
| ◇────── | 聚合 | 弱拥有关系 |
| ─────── | 关联 | 一般关联 |
可见性符号
| 符号 | 可见性 | Java |
|---|---|---|
| + | 公有 | public |
| - | 私有 | private |
| # | 保护 | protected |
| ~ | 包 | default |
参考资源
- 《设计模式:可复用面向对象软件的基础》- GoF
- 《Head First 设计模式》
- 《重构:改善既有代码的设计》- Martin Fowler
- 《Effective Java》- Joshua Bloch
- Refactoring Guru