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 的请标注本站原文地址