Skip to content

设计模式

设计模式是针对特定问题的可复用的优秀解决方案,是长期软件开发实践的经验总结。


一、设计模式概述

1.1 什么是设计模式

设计模式描述了在特定情境下,类和对象如何交互以解决一般性的设计问题。它不是具体代码,而是设计思想和指导。

1.2 设计模式的分类

类型关注点包含模式
创建型对象的创建过程工厂方法、抽象工厂、单例、建造者、原型
结构型类和对象的组合适配器、装饰器、代理、外观、桥接、组合、享元
行为型对象间的交互和职责分配观察者、策略、模板方法、责任链、命令、迭代器、中介者、备忘录、状态、访问者、解释器

二、创建型模式

2.1 工厂方法模式 (Factory Method)

意图:定义创建对象的接口,让子类决定实例化哪个类

结构

┌─────────────┐         ┌─────────────┐
│   Creator   │         │   Product   │
│ (抽象工厂)   │         │  (抽象产品)  │
├─────────────┤         └──────▲──────┘
│+factoryMethod()│              │
└──────▲──────┘              │
       │                      │
       │                      │
┌──────┴──────┐      ┌───────┴───────┐
│ConcreteCreator│     │ConcreteProduct│
│ (具体工厂)    │──→  │  (具体产品)   │
├─────────────┤      └───────────────┘
│+factoryMethod()│
└─────────────┘

核心代码

java
// 抽象工厂
public abstract class Creator {
    public abstract Product factoryMethod();
}

// 具体工厂
public class ConcreteCreator extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProduct();
    }
}

适用场景

  • 一个类不知道它所必须创建的对象的类
  • 希望由子类来指定创建的对象

2.2 抽象工厂模式 (Abstract Factory)

意图:提供一个接口,用于创建一系列相关或相互依赖的对象

与工厂方法的区别

模式产品等级产品族
工厂方法单一产品等级-
抽象工厂多个产品等级一组相关产品

适用场景

  • 系统需要创建一组相关的产品对象
  • 需要提供一个产品类库,只暴露接口

2.3 单例模式 (Singleton) ⭐

意图:保证一个类只有一个实例,并提供全局访问点

结构

┌─────────────────────┐
│      Singleton      │
├─────────────────────┤
│ - instance: Singleton│
├─────────────────────┤
│ - Singleton()       │  ← 私有构造函数
│ + getInstance()     │  ← 公有静态方法
└─────────────────────┘

实现方式

饿汉式(线程安全)

java
public class Singleton {
    private static final Singleton instance = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式(需注意线程安全)

java
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

适用场景

  • 系统只需要一个实例对象
  • 如:配置管理器、日志记录器、数据库连接池

2.4 建造者模式 (Builder)

意图:将复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示

适用场景

  • 创建复杂对象,对象由多个部分组成
  • 构建过程需要独立于创建对象的类

2.5 原型模式 (Prototype)

意图:用原型实例指定创建对象的种类,通过拷贝这些原型创建新对象

适用场景

  • 创建成本较高,通过复制现有对象更高效
  • 需要动态指定创建对象的类型

三、结构型模式

3.1 适配器模式 (Adapter) ⭐

意图:将一个类的接口转换成客户期望的另一个接口

结构

┌─────────┐     ┌─────────┐     ┌─────────┐
│  Client │────→│ Target  │     │ Adaptee │
│         │     │(目标接口)│     │(被适配者)│
└─────────┘     └────▲────┘     └────▲────┘
                     │               │
                     │               │
                ┌────┴───────────────┴────┐
                │        Adapter          │
                │       (适配器)          │
                ├─────────────────────────┤
                │ - adaptee: Adaptee      │
                │ + request()             │
                └─────────────────────────┘

核心代码

java
// 目标接口
public interface Target {
    void request();
}

// 被适配者
public class Adaptee {
    public void specificRequest() {
        // 原有的方法
    }
}

// 适配器
public class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        adaptee.specificRequest();  // 转换调用
    }
}

适用场景

  • 想使用现有类,但接口不符合需求
  • 需要复用不兼容接口的类

3.2 装饰器模式 (Decorator) ⭐

意图:动态地给对象添加额外职责,比继承更灵活

结构

                ┌─────────────┐
                │  Component  │
                │ (抽象构件)  │
                └──────▲──────┘

          ┌────────────┼────────────┐
          │                         │
┌─────────┴─────────┐    ┌─────────┴─────────┐
│ ConcreteComponent │    │     Decorator     │
│   (具体构件)      │    │   (抽象装饰)      │
└───────────────────┘    ├───────────────────┤
                         │ - component       │
                         └─────────▲─────────┘

                         ┌─────────┴─────────┐
                         │ ConcreteDecorator │
                         │   (具体装饰)      │
                         └───────────────────┘

核心代码

java
// 抽象构件
public interface Component {
    void operation();
}

// 具体构件
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        // 基本功能
    }
}

// 抽象装饰器
public abstract class Decorator implements Component {
    protected Component component;
    
    public Decorator(Component component) {
        this.component = component;
    }
    
    @Override
    public void operation() {
        component.operation();
    }
}

// 具体装饰器
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }
    
    @Override
    public void operation() {
        super.operation();
        addBehavior();  // 添加新行为
    }
    
    private void addBehavior() {
        // 新增功能
    }
}

适用场景

  • 不想增加子类来扩展功能
  • 动态添加或撤销功能
  • 如:Java IO流的设计

3.3 代理模式 (Proxy)

意图:为其他对象提供一种代理以控制对这个对象的访问

代理类型

  • 远程代理
  • 虚拟代理
  • 保护代理

3.4 外观模式 (Facade)

意图:为子系统中的一组接口提供一个统一的高层接口

适用场景

  • 为复杂子系统提供简单入口
  • 客户端与子系统解耦

3.5 桥接模式 (Bridge)

意图:将抽象部分与实现部分分离,使它们可以独立变化


3.6 组合模式 (Composite)

意图:将对象组合成树形结构表示"部分-整体"层次


3.7 享元模式 (Flyweight)

意图:运用共享技术有效支持大量细粒度对象


四、行为型模式

4.1 观察者模式 (Observer) ⭐

意图:定义对象间一对多依赖,当一个对象状态改变时,所有依赖者自动更新

结构

┌─────────────┐         ┌─────────────┐
│   Subject   │         │   Observer  │
│   (主题)    │◇───────→│  (观察者)   │
├─────────────┤         ├─────────────┤
│+attach()    │         │+update()    │
│+detach()    │         └──────▲──────┘
│+notify()    │                │
└──────▲──────┘                │
       │                       │
┌──────┴──────┐       ┌───────┴───────┐
│ConcreteSubject│      │ConcreteObserver│
└─────────────┘       └───────────────┘

核心代码

java
// 抽象主题
public interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObservers();
}

// 具体主题
public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;
    
    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }
    
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

// 观察者接口
public interface Observer {
    void update(int state);
}

适用场景

  • 一个对象改变需要通知其他对象
  • 对象之间松散耦合
  • 如:GUI事件处理、消息通知

4.2 策略模式 (Strategy) ⭐

意图:定义一系列算法,封装每个算法,使它们可以相互替换

结构

┌─────────────┐         ┌─────────────┐
│   Context   │◇───────→│  Strategy   │
│   (环境)    │         │  (抽象策略)  │
├─────────────┤         └──────▲──────┘
│+setStrategy()│               │
│+execute()   │                │
└─────────────┘    ┌───────────┼───────────┐
                   │           │           │
            ┌──────┴─────┐ ┌───┴───┐ ┌─────┴──────┐
            │StrategyA   │ │  ...  │ │ StrategyN  │
            └────────────┘ └───────┘ └────────────┘

核心代码

java
// 策略接口
public interface Strategy {
    void algorithm();
}

// 具体策略
public class ConcreteStrategyA implements Strategy {
    @Override
    public void algorithm() {
        // 算法A
    }
}

// 环境类
public class Context {
    private Strategy strategy;
    
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public void execute() {
        strategy.algorithm();
    }
}

适用场景

  • 多种算法,需要动态选择
  • 避免多重条件判断
  • 如:支付方式选择、排序算法选择

4.3 模板方法模式 (Template Method) ⭐

意图:定义算法骨架,将某些步骤延迟到子类实现

结构

┌─────────────────────┐
│   AbstractClass     │
│    (抽象类)         │
├─────────────────────┤
│ + templateMethod()  │  ← 定义算法骨架
│ # primitiveOp1()    │  ← 抽象方法
│ # primitiveOp2()    │  ← 抽象方法
│ # hook()            │  ← 钩子方法(可选重写)
└──────────▲──────────┘

┌──────────┴──────────┐
│   ConcreteClass     │
│    (具体类)         │
├─────────────────────┤
│ # primitiveOp1()    │  ← 实现具体步骤
│ # primitiveOp2()    │
└─────────────────────┘

核心代码

java
public abstract class AbstractClass {
    // 模板方法
    public final void templateMethod() {
        step1();
        step2();
        hook();
    }
    
    protected abstract void step1();
    protected abstract void step2();
    
    // 钩子方法
    protected void hook() {
        // 默认实现,子类可重写
    }
}

适用场景

  • 算法骨架固定,具体步骤可变
  • 提取公共行为到父类
  • 控制子类扩展

4.4 其他行为型模式简介

模式意图
责任链多个对象都有机会处理请求,连成一条链传递
命令将请求封装为对象,支持撤销、排队
迭代器顺序访问聚合对象的元素,不暴露内部表示
中介者用中介对象封装一系列对象交互
备忘录不破坏封装的前提下捕获对象内部状态
状态对象状态改变时改变其行为
访问者不改变类的前提下定义新操作
解释器给定语言,定义文法表示和解释器

五、设计模式对比总结

5.1 创建型模式对比

模式核心思想关键特征
工厂方法定义创建接口,子类决定实例化一个产品等级
抽象工厂创建一系列相关产品多个产品等级,产品族
单例只有一个实例私有构造,静态方法
建造者构建与表示分离复杂对象,分步构建
原型通过拷贝创建clone方法

5.2 结构型模式对比

模式核心思想关键特征
适配器接口转换包装不兼容接口
装饰器动态添加功能包装同类对象
代理控制访问与真实对象接口相同
外观简化接口提供统一入口
桥接抽象与实现分离两个独立变化维度

5.3 行为型模式对比

模式核心思想关键特征
观察者一对多依赖,状态变化通知发布-订阅
策略封装算法,可替换算法族
模板方法定义骨架,延迟实现继承,抽象方法
状态状态变化改变行为状态对象
责任链多个处理者,链式传递处理链

六、考试要点

高频考查模式

模式考查重点
单例模式实现方式、线程安全、应用场景
工厂方法与抽象工厂的区别
观察者模式结构、实现、应用场景
适配器模式结构、与装饰器的区别
装饰器模式结构、与继承的区别
策略模式结构、与状态模式的区别
模板方法结构、钩子方法

典型例题

题1:某系统需要将不同格式的文件统一转换为PDF格式,应使用什么模式? 答案:适配器模式

题2:需要动态给对象添加日志功能,不修改原有类,应使用什么模式? 答案:装饰器模式

题3:系统需要支持多种支付方式(微信、支付宝、银行卡),并可以动态切换,应使用什么模式? 答案:策略模式

模式识别口诀

创建分离用工厂,唯一实例单例当
适配转换接口异,装饰添加功能强
观察一多状态变,策略封装算法藏
模板骨架子类填,责任链条依次忙

上次更新:

如有转载或 CV 的请标注本站原文地址