背景

本文是Java修仙系列之设计模式。若想详细学习修仙系列,请点击首篇博文,开始学习。

设计模式

设计模式分为创建型结构型行为型三大类。

核心是:用固定模型解决重复出现的代码问题,降低耦合、提高复用,让代码更易维护。

一、创建型模式

核心:解决“对象创建”的问题,隐藏创建细节,解耦创建与使用,对应现实中“工厂造东西”的逻辑。

1. 单例模式

一、核心模型

现实模型:世界上只有一个太阳,所有人都共用这一个太阳,没有第二个;类比代码中,一个类只有一个实例,全局都能访问。

二、原理描述

保证一个类仅存在一个实例,并提供全局唯一访问点;避免多次实例化造成的资源浪费、状态混乱(比如连接池、全局配置类)。

三、核心特点

  • 私有构造器:禁止外部直接new实例
  • 全局唯一实例:类内部自己创建
  • 线程安全:双重检查锁+volatile保证多线程安全

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Singleton {
    // volatile:保证多线程下实例的可见性,防止指令重排(避免拿到未初始化的实例)
    private static volatile Singleton instance;

    // 1. 私有构造函数:禁止外部直接new(相当于“太阳不能被人造”)
    private Singleton() {}

    // 2. 全局访问方法:唯一获取实例的入口
    public static Singleton getInstance() {
        // 第一次检查:避免不必要的同步(大部分情况实例已存在,直接返回)
        if (instance == null) { 
            // 同步锁:保证多线程下只有一个线程能进入创建实例
            synchronized (Singleton.class) {
                // 第二次检查:防止多个线程同时进入同步块,重复创建实例
                if (instance == null) { 
                    instance = new Singleton(); // 唯一一次创建实例(造太阳)
                }
            }
        }
        return instance; // 全局共用同一个实例
    }
    
    // 示例方法:模拟太阳的功能(比如“发光”)
    public void showMessage() {
        System.out.println("Hello, I'm a Singleton instance!(我是唯一的实例)");
    }
    
    // 测试:无论怎么获取,都是同一个实例
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1 == singleton2); // true(证明只有一个实例)
        singleton1.showMessage();
    }
}

2. 工厂方法模式

一、核心模型

现实模型:手机工厂 → 抽象工厂(手机工厂)定义“造手机”的接口,具体工厂(华为工厂、苹果工厂)分别造华为手机、苹果手机;你要华为就找华为工厂,要苹果就找苹果工厂,不用自己造。

核心对应:抽象工厂=手机工厂(定义造手机接口),具体工厂=华为/苹果工厂(实现造手机),产品=华为/苹果手机(具体造出来的东西)。

二、原理描述

定义一个创建对象的接口(抽象工厂),但由子类(具体工厂)决定实例化哪个产品类;延迟实例化到子类,解耦“产品创建”和“产品使用”,新增产品只需加新工厂,不用改老代码。

三、核心特点

  • 一个工厂造一种产品(华为工厂只造华为手机)
  • 抽象工厂定义规范,具体工厂实现细节
  • 新增产品 → 新增具体产品+具体工厂,符合“开闭原则”

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 1. 产品接口:定义“手机”的通用功能(所有手机都能打电话)
interface Phone {
    void makeCall(); // 手机的核心功能:打电话
}

// 2. 具体产品A:华为手机(实现手机接口)
class HuaweiPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用华为手机打电话");
    }
}

// 2. 具体产品B:苹果手机(实现手机接口)
class IPhone implements Phone {
    @Override
    public void makeCall() {
        System.out.println("用苹果手机打电话");
    }
}

// 3. 抽象工厂:手机工厂(定义“造手机”的接口,不具体造)
abstract class PhoneFactory {
    // 工厂方法:造手机(由子类决定造哪种手机)
    public abstract Phone createPhone();
    
    // 业务方法:使用手机(不用管手机是谁造的,拿到就能用)
    public void usePhone() {
        Phone phone = createPhone(); // 工厂造手机
        phone.makeCall(); // 使用手机
    }
}

// 4. 具体工厂A:华为工厂(造华为手机)
class HuaweiFactory extends PhoneFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone(); // 华为工厂只造华为手机
    }
}

// 4. 具体工厂B:苹果工厂(造苹果手机)
class IPhoneFactory extends PhoneFactory {
    @Override
    public Phone createPhone() {
        return new IPhone(); // 苹果工厂只造苹果手机
    }
}

// 测试:要哪种手机,找对应的工厂
public class FactoryMethodDemo {
    public static void main(String[] args) {
        // 想要华为手机 → 找华为工厂
        PhoneFactory huaweiFactory = new HuaweiFactory();
        huaweiFactory.usePhone();  // 输出 "用华为手机打电话"
        
        // 想要苹果手机 → 找苹果工厂
        PhoneFactory iPhoneFactory = new IPhoneFactory();
        iPhoneFactory.usePhone();  // 输出 "用苹果手机打电话"
    }
}

3. 抽象工厂模式

一、核心模型

现实模型:家居品牌工厂 → 抽象工厂(家居工厂)定义“造椅子、造沙发”的接口(一套家居),具体工厂(现代家居工厂、欧式家居工厂)分别造“现代椅子+现代沙发”“欧式椅子+欧式沙发”;你要现代风格,就找现代工厂,一次性拿到一套配套的家居,不用分别找椅子厂、沙发厂。

核心对应:抽象工厂=家居工厂(定义造一套产品的接口),具体工厂=现代/欧式家居工厂(造一套配套产品),产品族=椅子+沙发(配套的一系列产品)。

二、原理描述

提供一个创建一系列相关/相互依赖对象(产品族)的接口,无需指定具体类;用于造“配套产品”,保证产品间能协同工作,新增产品族只需加新工厂。
关键区别(和工厂方法):工厂方法造“单一产品”,抽象工厂造“一套配套产品”。

三、核心特点

  • 一个工厂造一套产品(现代工厂造现代椅子+现代沙发)
  • 产品族内的产品相互配套,避免搭配混乱
  • 新增产品族 → 新增具体工厂,新增单个产品需修改抽象工厂(这点是缺点)

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// 1. 产品族:椅子和沙发(配套使用,属于同一套家居)
// 椅子接口(所有椅子都能坐)
interface Chair {
    void sitOn();
}

// 沙发接口(所有沙发都能躺)
interface Sofa {
    void lieOn();
}

// 2. 具体产品:现代风格(一套)
class ModernChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("坐现代风格椅子");
    }
}
class ModernSofa implements Sofa {
    @Override
    public void lieOn() {
        System.out.println("躺现代风格沙发");
    }
}

// 2. 具体产品:欧式风格(一套)
class EuropeanChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("坐欧式风格椅子");
    }
}
class EuropeanSofa implements Sofa {
    @Override
    public void lieOn() {
        System.out.println("躺欧式风格沙发");
    }
}

// 3. 抽象工厂:家居工厂(定义造“一套家居”的接口:造椅子+造沙发)
interface FurnitureFactory {
    Chair createChair(); // 造椅子
    Sofa createSofa();   // 造沙发(和椅子配套)
}

// 4. 具体工厂A:现代家居工厂(造现代风格一套家居)
class ModernFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new ModernChair(); // 现代椅子
    }
    
    @Override
    public Sofa createSofa() {
        return new ModernSofa(); // 现代沙发(和椅子配套)
    }
}

// 4. 具体工厂B:欧式家居工厂(造欧式风格一套家居)
class EuropeanFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new EuropeanChair(); // 欧式椅子
    }
    
    @Override
    public Sofa createSofa() {
        return new EuropeanSofa(); // 欧式沙发(和椅子配套)
    }
}

// 测试:要哪种风格,找对应的工厂,一次性拿到一套配套家居
public class AbstractFactoryDemo {
    public static void main(String[] args) {
        // 想要现代风格家居 → 找现代工厂
        FurnitureFactory modernFactory = new ModernFurnitureFactory();
        Chair modernChair = modernFactory.createChair();
        Sofa modernSofa = modernFactory.createSofa();
        modernChair.sitOn();  // 坐现代椅子
        modernSofa.lieOn();   // 躺现代沙发(配套)
        
        // 想要欧式风格家居 → 找欧式工厂
        FurnitureFactory europeanFactory = new EuropeanFurnitureFactory();
        Chair europeanChair = europeanFactory.createChair();
        Sofa europeanSofa = europeanFactory.createSofa();
        europeanChair.sitOn(); // 坐欧式椅子
        europeanSofa.lieOn();  // 躺欧式沙发(配套)
    }
}

补充:工厂方法 vs 抽象工厂(快速区分,加深记忆)

模式 核心模型 造什么 一句话记住
工厂方法 手机工厂(造单一产品) 一种产品 一个工厂造一种东西
抽象工厂 家居工厂(造配套产品) 一套产品(产品族) 一个工厂造一套东西

4. 建造者模式

一、核心模型

现实模型:组装电脑
CPU、内存、硬盘都是配件,一步一步装进去,最后组装成一台完整电脑。
核心:复杂对象分步骤创建,灵活搭配配置。

二、原理描述

复杂对象的创建使用分离,通过一步步设置属性,最后构建出对象;
不用写冗长构造方法,代码更清晰、更灵活。

三、核心特点

  • 一步一步创建复杂对象
  • 链式调用,优雅直观
  • 构造方法私有,必须通过Builder创建
  • 适合参数多、组合灵活的对象

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 产品:电脑(复杂对象,很多配件)
class Computer {
    private String cpu;
    private String memory;
    private String storage;

    // 私有构造:外部不能直接new
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.memory = builder.memory;
        this.storage = builder.storage;
    }

    // 建造者:专门负责一步一步创建Computer
    public static class Builder {
        private String cpu;
        private String memory;
        private String storage;

        // 链式设置CPU
        public Builder setCpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        // 链式设置内存
        public Builder setMemory(String memory) {
            this.memory = memory;
            return this;
        }

        // 链式设置硬盘
        public Builder setStorage(String storage) {
            this.storage = storage;
            return this;
        }

        // 构建:最终造出完整Computer对象
        public Computer build() {
            return new Computer(this);
        }
    }

    // 展示配置
    public void showSpecifications() {
        System.out.println("CPU: " + cpu + ", Memory: " + memory + ", Storage: " + storage);
    }
}

// 测试
public class BuilderDemo {
    public static void main(String[] args) {
        // 链式创建:一步一步装配件
        Computer computer = new Computer.Builder()
                .setCpu("Intel i7")
                .setMemory("16GB")
                .setStorage("512GB SSD")
                .build(); // 最终建造完成

        computer.showSpecifications();
    }
}

5. 原型模式

一、核心模型

现实模型:复印机
有一个原件,直接复印一份新的,不用从头重新制作。
核心:快速复制对象,不通过new创建。

二、原理描述

通过拷贝/克隆现有对象来创建新对象,
避免复杂对象重复创建的开销,提升效率。

三、核心特点

  • 基于拷贝创建对象,比直接new更快
  • 隐藏对象创建细节
  • 适合创建成本高、结构复杂的对象
  • Java 依靠 clone() 实现

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 原型接口:定义克隆能力
interface Prototype extends Cloneable {
    Prototype clone();
}

// 具体原型:要被复制的对象
class ConcretePrototype implements Prototype {
    private String data;

    // 构造:创建原始对象
    public ConcretePrototype(String data) {
        this.data = data;
    }

    // 克隆:复制一个一模一样的新对象
    @Override
    public Prototype clone() {
        return new ConcretePrototype(this.data);
    }

    // 展示数据
    public void showData() {
        System.out.println("Data: " + data);
    }
}

// 测试
public class PrototypeDemo {
    public static void main(String[] args) {
        // 1. 创建一个原件
        ConcretePrototype original = new ConcretePrototype("Original Data");
        
        // 2. 直接克隆(复印)一个新对象
        ConcretePrototype copy = (ConcretePrototype) original.clone();

        // 两个对象数据一样,但不是同一个
        original.showData();
        copy.showData();
    }
}

二、结构型模式

1. 适配器模式

一、核心模型

现实模型:电源转换插头.
中国扁头电器 不能直接插 欧洲圆孔插座;
通过转换适配器做中间适配,把原有接口转换成目标接口,让原本不兼容的两者正常工作。

核心对应:

  • 原有类:中国电器(已有功能、接口不匹配)
  • 目标接口:欧洲插座(系统期望的统一接口)
  • 适配器:转换插头(做包装、转接、兼容适配)

二、原理描述

原有不兼容的类,通过适配器包装转换为目标统一接口
不用修改原有代码,就能让接口不匹配的类协同工作,解决接口兼容问题。

三、核心特点

  • 不改动原有业务代码,通过中间层做适配
  • 兼容老系统、第三方接口、不同规格接口
  • 实现原有类和目标接口解耦

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 目标接口,客户所期待的接口
interface Target {
    void request();
}

// 需要适配的原有类,方法接口不匹配
class Adaptee {
    public void specificRequest() {
        System.out.println("Called specificRequest()");
    }
}

// 适配器:包装原有类,实现目标接口做转接
class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        // 适配转发:调用原有类方法
        adaptee.specificRequest();
    }
}

// 测试
public class AdapterDemo {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        target.request();
    }
}

插座场景版代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 中国电器自有接口
interface ChineseElectricalDevice {
    void chargeWithChinesePlug();
}

// 具体中国电器
class ChinesePhone implements ChineseElectricalDevice {
    @Override
    public void chargeWithChinesePlug() {
        System.out.println("中国手机使用中国扁平插头充电");
    }
}

// 欧洲插座目标接口
interface EuropeanSocket {
    void chargeWithEuropeanPlug();
}

// 适配器:转接兼容
class PlugAdapter implements EuropeanSocket {
    private ChineseElectricalDevice device;

    public PlugAdapter(ChineseElectricalDevice device) {
        this.device = device;
    }

    @Override
    public void chargeWithEuropeanPlug() {
        // 适配转发
        device.chargeWithChinesePlug();
    }
}

// 客户端测试
public class AdapterPatternExample {
    public static void main(String[] args) {
        ChinesePhone phone = new ChinesePhone();
        PlugAdapter adapter = new PlugAdapter(phone);
        adapter.chargeWithEuropeanPlug();
    }
}

2. 桥接模式

一、核心模型

现实模型:手机 + 各类软件
手机有不同品牌(苹果/安卓),软件有不同类型(游戏/音乐);
抽象维度(手机)实现维度(软件) 拆分开,用组合关联代替继承,两边可以各自独立扩展、互不影响。

核心对应:

  • 抽象层:手机(整体维度)
  • 实现层:软件(功能维度)
  • 桥接:通过组合把两层关联,做桥梁衔接

二、原理描述

抽象部分实现部分分离,让两者可以独立变化扩展;
不使用多层继承膨胀,改用组合依赖关联,降低耦合,灵活切换实现。

三、核心特点

  • 拆分两大变化维度,各自独立迭代
  • 用组合代替继承,避免类爆炸
  • 抽象和实现可动态绑定、灵活替换

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
          【接口 DrawAPI】
               ↓ 实现
      RedCircle    GreenCircle


【抽象类 Shape】
      ↓ 继承
    Circle

 Shape 内部持有 DrawAPI 引用  ← 桥接
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 实现层接口:绘制能力
interface DrawAPI {
    void drawCircle(int radius, int x, int y);
}

// 具体实现1
class RedCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle [Color: Red, Radius: " + radius + ", x: " + x + ", y:" + y + "]");
    }
}

// 具体实现2
class GreenCircle implements DrawAPI {
    @Override
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle [Color: Green, Radius: " + radius + ", x: " + x + ", y:" + y + "]");
    }
}

// 抽象层:形状,组合持有实现层引用
abstract class Shape {
    protected DrawAPI drawAPI; // 这就是桥!
    
    protected Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }
    
    public abstract void draw();
}

// 扩充抽象类
class Circle extends Shape {
    private int x, y, radius;
    
    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI); // super 构造只负责赋值,不负责创建
        this.x = x;
        this.y = y;
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        // 委托给实现层执行
        drawAPI.drawCircle(radius, x, y);
    }
}

// 测试
public class BridgeDemo {
    public static void main(String[] args) {
        Shape redCircle = new Circle(100, 100, 10, new RedCircle());
        Shape greenCircle = new Circle(200, 200, 20, new GreenCircle());
        
        redCircle.draw();
        greenCircle.draw();
    }
}

手机软件场景版代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 实现层抽象:软件
abstract class Software {
    public abstract void run();
}

// 具体实现:游戏软件
class GameSoftware extends Software {
    @Override
    public void run() {
        System.out.println("运行游戏软件");
    }
}

// 具体实现:音乐软件
class MusicPlayerSoftware extends Software {
    @Override
    public void run() {
        System.out.println("运行音乐播放器软件");
    }
}

// 抽象层:手机,组合持有软件引用
abstract class Phone {
    protected Software software;

    public Phone(Software software) {
        this.software = software;
    }

    public abstract void openSoftware();
}

// 扩充抽象:苹果手机
class ApplePhone extends Phone {
    public ApplePhone(Software software) {
        super(software);
    }

    @Override
    public void openSoftware() {
        System.out.println("苹果手机");
        software.run();
    }
}

// 扩充抽象:安卓手机
class AndroidPhone extends Phone {
    public AndroidPhone(Software software) {
        super(software);
    }

    @Override
    public void openSoftware() {
        System.out.println("安卓手机");
        software.run();
    }
}

// 客户端测试
public class BridgePatternExample {
    public static void main(String[] args) {
        Software gameSoftware = new GameSoftware();
        Software musicPlayerSoftware = new MusicPlayerSoftware();

        Phone appleGamePhone = new ApplePhone(gameSoftware);
        appleGamePhone.openSoftware();

        Phone androidMusicPhone = new AndroidPhone(musicPlayerSoftware);
        androidMusicPhone.openSoftware();
    }
}

3. 组合模式

一、核心模型

现实模型:电脑文件系统
根文件夹、子文件夹、文件形成树形结构;
文件夹(容器)可以包含文件和子文件夹,文件(叶子)是最小单元;
客户端统一对待单个叶子对象 和 容器组合对象,不用区分处理。

核心对应:

  • 抽象组件:文件/文件夹统一规范
  • 叶子节点:普通文件(无下级)
  • 容器节点:文件夹(可以包含子组件)

二、原理描述

将对象组织成树形层级结构,统一定义单个对象和组合对象的行为;
客户端以统一方式处理叶子和容器,不用感知内部层级差异,整体和部分一致对待。

三、核心特点

  • 树形结构收纳整体与部分
  • 叶子、容器统一接口,调用无感知
  • 方便层级遍历、递归处理(目录、菜单、组织架构)

四、Java 示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.ArrayList;
import java.util.List;

// 统一组件接口
interface Component {
    void show();
}

// 叶子节点:最小单元
class Leaf implements Component {
    private String name;
    
    public Leaf(String name) {
        this.name = name;
    }
    
    @Override
    public void show() {
        System.out.println("Leaf: " + name);
    }
}

// 容器节点:可以包含子组件
class Composite implements Component {
    private String name;
    private List<Component> children = new ArrayList<>();
    
    public Composite(String name) {
        this.name = name;
    }
    
    // 添加子组件
    public void add(Component component) {
        children.add(component);
    }
    
    @Override
    public void show() {
        System.out.println("Composite: " + name);
        for (Component component : children) {
            component.show();
        }
    }
}

// 测试
public class CompositeDemo {
    public static void main(String[] args) {
        Composite root = new Composite("Root");
        Leaf leaf1 = new Leaf("Leaf 1");
        Leaf leaf2 = new Leaf("Leaf 2");
        root.add(leaf1);
        root.add(leaf2);
        
        Composite subComposite = new Composite("Sub Composite");
        subComposite.add(new Leaf("Leaf 3"));
        root.add(subComposite);
        
        root.show();
    }
}

文件夹场景版代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import java.util.ArrayList;

// 抽象组件:统一规范文件和文件夹行为
abstract class Component {
    protected String name;

    public Component(String name) {
        this.name = name;
    }

    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    public Component getChild(int index) {
        throw new UnsupportedOperationException();
    }

    public abstract void operation();
}

// 叶子节点:文件
class Leaf extends Component {
    public Leaf(String name) {
        super(name);
    }

    @Override
    public void operation() {
        System.out.println("执行单个对象 " + name + " 的操作");
    }
}

// 容器节点:文件夹
class Composite extends Component {
    private ArrayList<Component> children = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }

    @Override
    public void add(Component component) {
        children.add(component);
    }

    @Override
    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public Component getChild(int index) {
        return children.get(index);
    }

    @Override
    public void operation() {
        System.out.println("执行组合对象 " + name + " 的操作");
        for (Component component : children) {
            component.operation();
        }
    }
}

// 客户端测试
public class CompositeDemo2 {
    public static void main(String[] args) {
        Composite root = new Composite("根文件夹");
        Leaf file1 = new Leaf("文件1");
        Leaf file2 = new Leaf("文件2");

        Composite subFolder = new Composite("子文件夹");
        root.add(file1);
        root.add(file2);
        root.add(subFolder);

        Leaf file3 = new Leaf("文件3");
        subFolder.add(file3);

        root.operation();
    }
}

4. 装饰器模式

一、核心模型

现实模型:汉堡 / 咖啡加配料
基础汉堡/咖啡是核心对象,生菜、芝士、牛奶、糖都是动态配料
不用创建无数子类,而是一层一层包裹,动态给对象加功能。

核心对应:

  • 基础对象:原味汉堡、黑咖啡
  • 装饰器:配料(生菜、芝士、牛奶、糖)
  • 特点:层层包裹、动态增强、不修改原类

二、原理描述

不改变原有对象的前提下,动态地给对象添加额外功能
通过组合包裹的方式,一层一层装饰,比继承更灵活。

三、核心特点

  • 动态增强对象功能
  • 避免子类爆炸
  • 装饰与被装饰实现同一接口
  • 可多层嵌套装饰

四、Java 实现

装饰器模式-咖啡版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 抽象组件接口
interface Coffee {
    double cost();
    String description();
}

// 具体组件:基础咖啡
class SimpleCoffee implements Coffee {
    @Override
    public double cost() {
        return 5.0;
    }
    
    @Override
    public String description() {
        return "Simple Coffee";
    }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    
    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }
    
    @Override
    public String description() {
        return decoratedCoffee.description();
    }
}

// 具体装饰器:加牛奶
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return super.cost() + 1.5;
    }
    
    @Override
    public String description() {
        return super.description() + ", with milk";
    }
}

// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return super.cost() + 0.5;
    }
    
    @Override
    public String description() {
        return super.description() + ", with sugar";
    }
}

// 测试
public class DecoratorDemo {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.description() + " $" + coffee.cost());
        
        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.description() + " $" + coffee.cost());
        
        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.description() + " $" + coffee.cost());
    }
}
装饰器模式-汉堡版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 汉堡接口
interface Burger {
    String getDescription();
    double getCost();
}

// 基础汉堡
class BasicBurger implements Burger {
    @Override
    public String getDescription() {
        return "基础汉堡(面包夹肉饼)";
    }

    @Override
    public double getCost() {
        return 10.0;
    }
}

// 装饰器抽象类
abstract class BurgerDecorator implements Burger {
    protected Burger burger;

    public BurgerDecorator(Burger burger) {
        this.burger = burger;
    }

    @Override
    public String getDescription() {
        return burger.getDescription();
    }

    @Override
    public double getCost() {
        return burger.getCost();
    }
}

// 生菜装饰器
class LettuceDecorator extends BurgerDecorator {
    public LettuceDecorator(Burger burger) {
        super(burger);
    }

    @Override
    public String getDescription() {
        return burger.getDescription() + " + 生菜";
    }

    @Override
    public double getCost() {
        return burger.getCost() + 2.0;
    }
}

// 芝士装饰器
class CheeseDecorator extends BurgerDecorator {
    public CheeseDecorator(Burger burger) {
        super(burger);
    }

    @Override
    public String getDescription() {
        return burger.getDescription() + " + 芝士";
    }

    @Override
    public double getCost() {
        return burger.getCost() + 3.0;
    }
}

// 客户端
public class DecoratorPatternExample {
    public static void main(String[] args) {
        Burger basicBurger = new BasicBurger();
        System.out.println(basicBurger.getDescription() + ",价格:" + basicBurger.getCost());

        Burger lettuceBurger = new LettuceDecorator(basicBurger);
        System.out.println(lettuceBurger.getDescription() + ",价格:" + lettuceBurger.getCost());

        Burger lettuceCheeseBurger = new CheeseDecorator(lettuceBurger);
        System.out.println(lettuceCheeseBurger.getDescription() + ",价格:" + lettuceCheeseBurger.getCost());
    }
}

5. 外观模式

一、核心模型

现实模型:医院导医台 / 电脑开机
系统内部很复杂(挂号、诊断、检查、拿药),
给用户一个简单入口,不用关心内部细节。

核心对应:

  • 复杂子系统:医院各个部门、电脑硬件
  • 外观类:导医台、电脑开机键
  • 作用:统一入口、简化调用、隐藏复杂流程

二、原理描述

复杂子系统提供一个统一高层接口,让客户端更简单地使用系统;
隐藏内部复杂性,只暴露简单易用的入口。

三、核心特点

  • 简化复杂调用
  • 解耦客户端与子系统
  • 提供统一入口
  • 不修改子系统,只做封装

四、Java 实现

外观模式-电脑版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 子系统类1
class CPU {
    public void start() {
        System.out.println("CPU starting...");
    }
    public void shutdown() {
        System.out.println("CPU shutting down...");
    }
}

// 子系统类2
class Memory {
    public void load() {
        System.out.println("Memory loading...");
    }
    public void clear() {
        System.out.println("Memory clearing...");
    }
}

// 子系统类3
class HardDrive {
    public void read() {
        System.out.println("HardDrive reading...");
    }
    public void write() {
        System.out.println("HardDrive writing...");
    }
}

// 外观类
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;
    
    public ComputerFacade() {
        cpu = new CPU();
        memory = new Memory();
        hardDrive = new HardDrive();
    }
    
    public void startComputer() {
        System.out.println("Starting computer...");
        cpu.start();
        memory.load();
        hardDrive.read();
    }
    
    public void shutdownComputer() {
        System.out.println("Shutting down computer...");
        cpu.shutdown();
        memory.clear();
        hardDrive.write();
    }
}

// 测试
public class FacadeDemo {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.startComputer();
        computer.shutdownComputer();
    }
}
外观模式-医院版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 挂号处
class RegistrationDesk {
    public void register() {
        System.out.println("在挂号处完成挂号");
    }
}

// 科室
class Department {
    public void diagnose() {
        System.out.println("在科室进行病情诊断");
    }
}

// 检验科
class Laboratory {
    public void test() {
        System.out.println("在检验科进行检查");
    }
}

// 药房
class Pharmacy {
    public void getMedicine() {
        System.out.println("在药房领取药品");
    }
}

// 导诊台外观类
class GuideDeskFacade {
    private RegistrationDesk registrationDesk;
    private Department department;
    private Laboratory laboratory;
    private Pharmacy pharmacy;

    public GuideDeskFacade() {
        registrationDesk = new RegistrationDesk();
        department = new Department();
        laboratory = new Laboratory();
        pharmacy = new Pharmacy();
    }

    public void seeDoctor() {
        registrationDesk.register();
        department.diagnose();
        laboratory.test();
        pharmacy.getMedicine();
        System.out.println("看病流程完成");
    }
}

// 客户端
public class HospitalGuideDeskExample {
    public static void main(String[] args) {
        GuideDeskFacade guideDesk = new GuideDeskFacade();
        guideDesk.seeDoctor();
    }
}

6. 享元模式

一、核心模型

现实模型:共享单车 / 画图工具
大量重复对象(同颜色、同型号),只创建一份共享
不同位置/状态作为外部信息传入,节省内存。

核心对应:

  • 共享内部状态:颜色、车型
  • 外部状态:位置、坐标
  • 工厂:统一管理共享对象

二、原理描述

运用共享技术,大量复用细粒度对象,
可共享的部分(内部状态)独立部分(外部状态) 分离,
大幅减少对象数量,节省内存。

三、核心特点

  • 共享相同对象,减少内存
  • 区分内部状态、外部状态
  • 使用工厂统一管理共享池
  • 适合大量重复对象场景

四、Java 实现

享元模式-画图版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.util.HashMap;
import java.util.Map;

// 享元接口
interface Shape {
    void draw();
}

// 具体享元类
class Circle implements Shape {
    private String color; // 内部状态(共享)
    private int x, y, radius;

    public Circle(String color) {
        this.color = color;
    }

    public void setX(int x) { this.x = x; }
    public void setY(int y) { this.y = y; }
    public void setRadius(int radius) { this.radius = radius; }

    @Override
    public void draw() {
        System.out.println("Drawing circle [Color: " + color + ", x: " + x + ", y: " + y + ", radius: " + radius + "]");
    }
}

// 享元工厂
class ShapeFactory {
    private static final Map<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle) circleMap.get(color);
        if (circle == null) {
            circle = new Circle(color);
            circleMap.put(color, circle);
        }
        return circle;
    }
}

// 测试
public class FlyweightDemo {
    public static void main(String[] args) {
        Circle circle1 = (Circle) ShapeFactory.getCircle("Red");
        circle1.setX(10);
        circle1.setY(20);
        circle1.setRadius(5);
        circle1.draw();

        Circle circle2 = (Circle) ShapeFactory.getCircle("Red");
        circle2.setX(30);
        circle2.setY(40);
        circle2.setRadius(10);
        circle2.draw();

        System.out.println("同一对象: " + (circle1 == circle2));
    }
}
享元模式-共享单车版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.HashMap;
import java.util.Map;

interface Bike {
    void ride(String location);
}

class SharedBike implements Bike {
    private String model;
    private String color;

    public SharedBike(String model, String color) {
        this.model = model;
        this.color = color;
    }

    @Override
    public void ride(String location) {
        System.out.println("骑 " + color + " " + model + ",位置: " + location);
    }
}

class BikeFactory {
    private static Map<String, Bike> bikeMap = new HashMap<>();

    public static Bike getBike(String model, String color) {
        String key = model + "-" + color;
        if (!bikeMap.containsKey(key)) {
            bikeMap.put(key, new SharedBike(model, color));
        }
        return bikeMap.get(key);
    }
}

public class FlyweightDemo {
    public static void main(String[] args) {
        SharedBike bike1 = (SharedBike) BikeFactory.getBike("山地车", "蓝色");
        bike1.ride("公园门口");

        SharedBike bike2 = (SharedBike) BikeFactory.getBike("山地车", "蓝色");
        bike2.ride("商场门口");

        System.out.println("同一对象: " + (bike1 == bike2));
    }
}

7. 代理模式

一、核心模型

现实模型:房屋中介 / 图片懒加载
不直接访问真实对象,而是通过代理对象间接访问;
代理可做:权限控制、延迟加载、日志、增强功能。

核心对应:

  • 真实对象:房东、真实图片
  • 代理对象:中介、代理图片
  • 作用:控制访问、增强功能、延迟加载

二、原理描述

为一个对象提供一个代理,由代理控制对原对象的访问;
可在调用前后做增强,不修改原对象。

三、核心特点

  • 保护/控制真实对象访问
  • 可延迟加载(懒加载)
  • 可增强功能(日志、权限、缓存)
  • 代理与真实对象实现同一接口

四、Java 实现

代理模式-图片版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 抽象主题接口
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("Loading " + filename);
    }
    
    @Override
    public void display() {
        System.out.println("Displaying " + filename);
    }
}

// 代理类
class ProxyImage implements Image {
    private String filename;
    private RealImage realImage;
    
    public ProxyImage(String filename) {
        this.filename = filename;
    }
    
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

// 测试
public class ProxyDemo {
    public static void main(String[] args) {
        Image image = new ProxyImage("test_image.jpg");
        image.display(); // 懒加载(延迟加载)
        image.display(); // 缓存(复用对象)
    }
}
代理模式-租房版
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 租房接口
interface RentHouse {
    void rent();
}

// 房东(真实对象)
class Landlord implements RentHouse {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

// 中介(代理对象)
class HouseAgent implements RentHouse {
    private Landlord landlord;

    public HouseAgent(Landlord landlord) {
        this.landlord = landlord;
    }

    @Override
    public void rent() {
        System.out.println("中介筛选房子");
        System.out.println("中介安排看房");
        landlord.rent();
        System.out.println("中介协助签合同");
    }
}

// 客户端
public class ProxyPatternExample {
    public static void main(String[] args) {
        Landlord landlord = new Landlord();
        HouseAgent agent = new HouseAgent(landlord);
        agent.rent();
    }
}

三、行为型模式

1. 责任链模式

一、核心模型

现实模型:公司请假审批
请假天数不同,审批人不同(项目经理→部门经理→总经理),请假申请沿审批链传递,直到有审批人能处理。

核心对应:

  • 责任链:项目经理→部门经理→总经理(依次传递)
  • 请求:请假申请(天数不同,处理者不同)
  • 特点:请求沿链传递、谁能处理谁处理、不直接耦合

二、原理描述

将多个处理者组成一条责任链,请求沿着这条链依次传递,直到有一个处理者能够处理该请求;
每个处理者只负责自己权限范围内的请求,无权处理则传递给下一个处理者,降低请求发送者与处理者的耦合。

三、核心特点

  • 请求沿责任链传递,无需知道具体处理者
  • 每个处理者只处理自己职责内的请求
  • 可动态调整责任链顺序和处理者
  • 避免请求发送者与多个处理者直接耦合

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 抽象处理者
abstract class Handler {
    protected Handler next;
    
    public void setNext(Handler next) {
        this.next = next;
    }
    
    public abstract void handleRequest(String request);
}

// 具体处理者A
class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.contains("A")) {
            System.out.println("Handler A processed the request: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}

// 具体处理者B
class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if (request.contains("B")) {
            System.out.println("Handler B processed the request: " + request);
        } else if (next != null) {
            next.handleRequest(request);
        }
    }
}

// 测试
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        
        handlerA.setNext(handlerB);
        
        handlerA.handleRequest("Request for A");
        handlerA.handleRequest("Request for B");
        handlerA.handleRequest("Request for C");
    }
}

责任链模式-请假

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 抽象处理者类
abstract class Approver {
    protected Approver nextApprover;

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    public abstract void processRequest(int days);
}

// 项目经理类
class ProjectManager extends Approver {
    @Override
    public void processRequest(int days) {
        if (days <= 1) {
            System.out.println("项目经理批准了 " + days + " 天的请假申请。");
        } else if (nextApprover != null) {
            nextApprover.processRequest(days);
        }
    }
}

// 部门经理类
class DepartmentManager extends Approver {
    @Override
    public void processRequest(int days) {
        if (days > 1 && days <= 3) {
            System.out.println("部门经理批准了 " + days + " 天的请假申请。");
        } else if (nextApprover != null) {
            nextApprover.processRequest(days);
        }
    }
}

// 总经理类
class GeneralManager extends Approver {
    @Override
    public void processRequest(int days) {
        if (days > 3) {
            System.out.println("总经理批准了 " + days + " 天的请假申请。");
        }
    }
}

// 客户端类
public class LeaveApprovalChain {
    public static void main(String[] args) {
        // 创建各个审批者
        Approver projectManager = new ProjectManager();
        Approver departmentManager = new DepartmentManager();
        Approver generalManager = new GeneralManager();

        // 设置责任链顺序
        projectManager.setNextApprover(departmentManager);
        departmentManager.setNextApprover(generalManager);

        // 模拟不同天数的请假申请
        projectManager.processRequest(1);
        projectManager.processRequest(2);
        projectManager.processRequest(5);
    }
}

2. 命令模式

一、核心模型

现实模型:餐厅点餐
顾客(客户端)点餐,服务员(调用者)记录订单(命令),厨师(接收者)按订单做菜;顾客无需直接找厨师,服务员统一调度订单。

核心对应:

  • 命令:订单(封装点餐请求)
  • 调用者:服务员(管理、执行命令)
  • 接收者:厨师(执行具体操作)
  • 特点:请求封装、解耦客户端与接收者

二、原理描述

将请求封装成独立的命令对象,使请求的发送者(客户端)与接收者(执行请求的对象)解耦;
命令对象可被存储、排队、记录日志,实现请求的灵活调度(顺序执行、撤销)。

三、核心特点

  • 解耦请求发送者与接收者,互不依赖
  • 请求被封装成命令对象,可灵活管理(排队、日志、撤销)
  • 可扩展新命令,无需修改原有调用者和接收者
  • 调用者只需调用命令的执行方法,无需关心具体实现

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 命令接口
interface Command {
    void execute();
}

// 具体命令
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    @Override
    public void execute() {
        light.on();
    }
}

// 接收者
class Light {
    public void on() {
        System.out.println("Light is ON");
    }
    public void off() {
        System.out.println("Light is OFF");
    }
}

// 调用者
class RemoteControl {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

// 测试
public class CommandDemo {
    public static void main(String[] args) {
        Light light = new Light();
        Command lightOn = new LightOnCommand(light);
        RemoteControl remote = new RemoteControl();
        
        remote.setCommand(lightOn);
        remote.pressButton();
    }
}

命令模式-餐厅点餐

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 命令接口
interface Command {
    void execute();
}

// 具体命令类:点炒饭
class FriedRiceCommand implements Command {
    private Chef chef;

    public FriedRiceCommand(Chef chef) {
        this.chef = chef;
    }

    @Override
    public void execute() {
        chef.cookFriedRice();
    }
}

// 具体命令类:点炒面
class FriedNoodlesCommand implements Command {
    private Chef chef;

    public FriedNoodlesCommand(Chef chef) {
        this.chef = chef;
    }

    @Override
    public void execute() {
        chef.cookFriedNoodles();
    }
}

// 厨师类,负责执行具体的做菜操作
class Chef {
    public void cookFriedRice() {
        System.out.println("厨师正在做炒饭");
    }

    public void cookFriedNoodles() {
        System.out.println("厨师正在做炒面");
    }
}

// 服务员类,负责接收、排队和执行命令
class Waiter {
    private Command command;

    public void takeOrder(Command command) {
        this.command = command;
    }

    public void placeOrder() {
        if (command != null) {
            command.execute();
        }
    }
}

// 客户端类
public class RestaurantCommandPattern {
    public static void main(String[] args) {
        Chef chef = new Chef();
        Waiter waiter = new Waiter();

        Command friedRiceCommand = new FriedRiceCommand(chef);
        waiter.takeOrder(friedRiceCommand);
        waiter.placeOrder();

        Command friedNoodlesCommand = new FriedNoodlesCommand(chef);
        waiter.takeOrder(friedNoodlesCommand);
        waiter.placeOrder();
    }
}

3. 解释器模式

一、核心模型

现实模型:简单数学表达式计算器
小学课堂上,老师(解释器)根据语法规则,计算「2+3」「5-1」等表达式;数字和运算符是语法元素,老师按规则解释计算。

核心对应:

  • 抽象表达式:语法规则抽象
  • 具体表达式:数字、加减运算符
  • 解释器:解析表达式、计算结果
  • 特点:解析特定语法、可扩展语法规则

二、原理描述

定义一种语言的语法规则,构建解释器解析这种语言的句子(数学表达式、简单指令);
将语法拆分为抽象表达式和具体表达式,递归调用解释器完成解析与执行。

三、核心特点

  • 专门用于解析特定语法场景(表达式、配置文件)
  • 语法规则可通过新增具体表达式扩展
  • 语法简单易用,复杂语法会导致类爆炸
  • 核心:解析语法、执行逻辑

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 抽象表达式接口
interface Expression {
    boolean interpret(String context);
}

// 终结符表达式
class TerminalExpression implements Expression {
    private String data;
    
    public TerminalExpression(String data) {
        this.data = data;
    }
    
    @Override
    public boolean interpret(String context) {
        return context.contains(data);
    }
}

// 非终结符表达式:或表达式
class OrExpression implements Expression {
    private Expression expr1;
    private Expression expr2;
    
    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }
    
    @Override
    public boolean interpret(String context) {
        return expr1.interpret(context) || expr2.interpret(context);
    }
}

// 测试
public class InterpreterDemo {
    public static void main(String[] args) {
        Expression isAdmin = new TerminalExpression("Admin");
        Expression isManager = new TerminalExpression("Manager");
        Expression isAdminOrManager = new OrExpression(isAdmin, isManager);
        
        System.out.println("User is admin or manager? " + isAdminOrManager.interpret("Admin"));
    }
}

解释器模式-数学表达式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 抽象表达式类
abstract class Expression {
    public abstract int interpret();
}

// 数字表达式类
class NumberExpression extends Expression {
    private int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    @Override
    public int interpret() {
        return number;
    }
}

// 加法表达式类
class AdditionExpression extends Expression {
    private Expression left;
    private Expression right;

    public AdditionExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret() {
        return left.interpret() + right.interpret();
    }
}

// 减法表达式类
class SubtractionExpression extends Expression {
    private Expression left;
    private Expression right;

    public SubtractionExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret() {
        return left.interpret() - right.interpret();
    }
}

// 客户端类
public class InterpreterPatternExample {
    public static void main(String[] args) {
        Expression expression = new AdditionExpression(
                new NumberExpression(2),
                new NumberExpression(3)
        );
        int result = expression.interpret();
        System.out.println("表达式 2 + 3 的结果是: " + result);

        Expression subtractionExpression = new SubtractionExpression(
                new NumberExpression(5),
                new NumberExpression(1)
        );
        int subtractionResult = subtractionExpression.interpret();
        System.out.println("表达式 5 - 1 的结果是: " + subtractionResult);
    }
}

4. 迭代器模式

一、核心模型

现实模型:图书馆书架书籍遍历
管理员通过迭代器(遍历工具)遍历书架(聚合对象)书籍,无需知道书架内部存储结构。

核心对应:

  • 聚合对象:书架
  • 迭代器:遍历工具(hasNext、next)
  • 元素:书籍
  • 特点:遍历与存储分离、隐藏内部结构

二、原理描述

提供统一方式遍历聚合对象,将遍历逻辑从聚合对象中分离;
客户端无需了解集合内部存储结构,即可统一遍历元素。

三、核心特点

  • 解耦聚合对象与遍历操作
  • 统一遍历接口,适配不同集合
  • 可扩展正向/反向等自定义迭代器
  • 隐藏集合内部实现细节

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

// 集合类
class NameRepository implements Iterable<String> {
    private List<String> names = new ArrayList<>();
    
    public NameRepository() {
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
    }
    
    @Override
    public Iterator<String> iterator() {
        return names.iterator();
    }
}

// 测试
public class IteratorDemo {
    public static void main(String[] args) {
        NameRepository names = new NameRepository();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

迭代器模式-书架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.ArrayList;
import java.util.List;

// 书籍类
class Book {
    private String title;

    public Book(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
}

// 迭代器接口
interface Iterator {
    boolean hasNext();
    Book next();
}

// 书架类,聚合对象
class Bookshelf {
    private List<Book> books = new ArrayList<>();

    public void addBook(Book book) {
        books.add(book);
    }

    public Iterator createIterator() {
        return new BookshelfIterator();
    }

    // 迭代器内部类
    private class BookshelfIterator implements Iterator {
        private int index = 0;

        @Override
        public boolean hasNext() {
            return index < books.size();
        }

        @Override
        public Book next() {
            Book book = books.get(index);
            index++;
            return book;
        }
    }
}

// 客户端类
public class IteratorPatternExample {
    public static void main(String[] args) {
        Bookshelf bookshelf = new Bookshelf();
        bookshelf.addBook(new Book("Book 1"));
        bookshelf.addBook(new Book("Book 2"));
        bookshelf.addBook(new Book("Book 3"));

        Iterator iterator = bookshelf.createIterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            System.out.println("当前书籍: " + book.getTitle());
        }
    }
}

5. 中介者模式

一、核心模型

现实模型:机场塔台调度
多架飞机无需直接通信,通过塔台统一协调起降;飞机只和塔台交互,避免网状依赖。

核心对应:

  • 中介者:机场塔台
  • 同事对象:各架飞机
  • 特点:统一协调、解耦同事、集中管理交互

二、原理描述

定义中介者对象,封装多个同事对象的交互逻辑;
同事之间不直接通信,全部通过中介者中转,降低耦合度。

三、核心特点

  • 消除同事间网状依赖,改为星型依赖
  • 交互逻辑集中在中介者,便于维护
  • 新增同事只需适配中介者,不改动其他同事
  • 缺点:中介者易逻辑臃肿,成为上帝类

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.util.ArrayList;
import java.util.List;

// 抽象中介者
interface ChatMediator {
    void sendMessage(String msg, User user);
    void addUser(User user);
}

// 具体中介者
class ChatMediatorImpl implements ChatMediator {
    private List<User> users = new ArrayList<>();
    
    @Override
    public void addUser(User user) {
        users.add(user);
    }
    
    @Override
    public void sendMessage(String msg, User user) {
        for (User u : users) {
            if (u != user) {
                u.receive(msg);
            }
        }
    }
}

// 同事类
abstract class User {
    protected ChatMediator mediator;
    protected String name;
    
    public User(ChatMediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }
    
    public abstract void send(String msg);
    public abstract void receive(String msg);
}

// 具体同事类
class ChatUser extends User {
    public ChatUser(ChatMediator mediator, String name) {
        super(mediator, name);
    }
    
    @Override
    public void send(String msg) {
        System.out.println(name + " sends: " + msg);
        mediator.sendMessage(msg, this);
    }
    
    @Override
    public void receive(String msg) {
        System.out.println(name + " receives: " + msg);
    }
}

// 测试
public class MediatorDemo {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatMediatorImpl();
        User user1 = new ChatUser(mediator, "Alice");
        User user2 = new ChatUser(mediator, "Bob");
        User user3 = new ChatUser(mediator, "Charlie");
        
        mediator.addUser(user1);
        mediator.addUser(user2);
        mediator.addUser(user3);
        
        user1.send("Hello everyone!");
    }
}

中介者模式-飞机塔台

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.ArrayList;
import java.util.List;

// 飞机抽象类
abstract class Plane {
    protected AirportTower tower;
    protected String name;

    public Plane(AirportTower tower, String name) {
        this.tower = tower;
        this.name = name;
    }

    public abstract void sendRequest(String message);
    public abstract void receiveMessage(String message);
}

// 具体飞机类
class ConcretePlane extends Plane {
    public ConcretePlane(AirportTower tower, String name) {
        super(tower, name);
    }

    @Override
    public void sendRequest(String message) {
        System.out.println(name + " 发送请求: " + message);
        tower.notifyPlanes(this, message);
    }

    @Override
    public void receiveMessage(String message) {
        System.out.println(name + " 收到消息: " + message);
    }
}

// 机场塔台类(中介者)
class AirportTower {
    private List<Plane> planes = new ArrayList<>();

    public void registerPlane(Plane plane) {
        planes.add(plane);
    }

    public void notifyPlanes(Plane sender, String message) {
        for (Plane plane : planes) {
            if (plane != sender) {
                plane.receiveMessage(sender.name + " 说: " + message);
            }
        }
    }
}

// 客户端类
public class AirportMediatorPattern {
    public static void main(String[] args) {
        AirportTower tower = new AirportTower();
        Plane plane1 = new ConcretePlane(tower, "飞机1");
        Plane plane2 = new ConcretePlane(tower, "飞机2");
        Plane plane3 = new ConcretePlane(tower, "飞机3");

        tower.registerPlane(plane1);
        tower.registerPlane(plane2);
        tower.registerPlane(plane3);

        plane1.sendRequest("我准备起飞");
    }
}

6. 备忘录模式

一、核心模型

现实模型:文档编辑撤销功能
Word编辑文档,每步操作保存状态快照,撤销可回滚到历史版本;
发起人(文档)、备忘录(状态快照)、管理者(保管快照)三者协作。

核心对应:

  • 发起人:文档(创建/恢复状态)
  • 备忘录:存储对象内部状态
  • 管理者:保管、存取备忘录
  • 特点:状态备份、可撤销、不破坏封装

二、原理描述

在不破坏封装的前提下,捕获对象内部状态并保存;
后续可通过保存的备忘录,将对象回滚到历史状态,实现撤销、回滚。

三、核心特点

  • 支持对象状态备份与回滚、撤销操作
  • 不对外暴露内部字段,保持封装性
  • 备忘录只读,仅发起人可恢复
  • 管理者只负责保管,不修改备忘录内容

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.Stack;

// 发起人
class Originator {
    private String state;
    
    public void setState(String state) {
        this.state = state;
        System.out.println("Setting state to " + state);
    }
    
    public String getState() {
        return state;
    }
    
    public Memento saveStateToMemento() {
        return new Memento(state);
    }
    
    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
        System.out.println("State restored to " + state);
    }
}

// 备忘录
class Memento {
    private final String state;
    
    public Memento(String state) {
        this.state = state;
    }
    
    public String getState() {
        return state;
    }
}

// 管理者
class Caretaker {
    private Stack<Memento> mementoStack = new Stack<>();
    
    public void add(Memento state){
        mementoStack.push(state);
    }
    
    public Memento get(){
        return mementoStack.pop();
    }
}

// 测试
public class MementoDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();
        
        originator.setState("State1");
        caretaker.add(originator.saveStateToMemento());
        
        originator.setState("State2");
        caretaker.add(originator.saveStateToMemento());
        
        originator.setState("State3");
        originator.getStateFromMemento(caretaker.get());
    }
}

备忘录模式-文档撤销

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 备忘录类,存储文档状态
class DocumentMemento {
    private String content;

    public DocumentMemento(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

// 文档类(发起人)
class Document {
    private String content;
    private Caretaker caretaker;

    public Document(Caretaker caretaker) {
        this.caretaker = caretaker;
    }

    public void setContent(String content) {
        this.content = content;
        caretaker.saveMemento(createMemento());
    }

    public String getContent() {
        return content;
    }

    public DocumentMemento createMemento() {
        return new DocumentMemento(content);
    }

    public void restoreFromMemento(DocumentMemento memento) {
        this.content = memento.getContent();
    }

    public void undo() {
        DocumentMemento memento = caretaker.getPreviousMemento();
        if (memento != null) {
            restoreFromMemento(memento);
        }
    }
}

// 管理者类
class Caretaker {
    private java.util.List<DocumentMemento> mementos = new java.util.ArrayList<>();
    private int currentIndex = -1;

    public void saveMemento(DocumentMemento memento) {
        if (currentIndex < mementos.size() - 1) {
            mementos = mementos.subList(0, currentIndex + 1);
        }
        mementos.add(memento);
        currentIndex++;
    }

    public DocumentMemento getPreviousMemento() {
        if (currentIndex > 0) {
            currentIndex--;
            return mementos.get(currentIndex);
        }
        return null;
    }
}

// 客户端类
public class DocumentMementoPattern {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Document document = new Document(caretaker);

        document.setContent("第一段文字");
        System.out.println("当前内容: " + document.getContent());

        document.setContent("第一段文字,第二段文字");
        System.out.println("当前内容: " + document.getContent());

        document.undo();
        System.out.println("撤销后内容: " + document.getContent());
    }
}

7. 观察者模式

一、核心模型

现实模型:天气预报
气象站(主题)发布天气,手机APP、电视台(观察者)订阅;主题状态变更,自动推送所有观察者更新。

核心对应:

  • 主题:被观察者,维护观察者列表
  • 观察者:订阅者,接收通知自动更新
  • 特点:一对多、发布-订阅、自动通知

二、原理描述

定义一对多依赖,一个主题绑定多个观察者;
主题状态变化时,自动广播通知所有观察者,观察者被动更新自身状态。

三、核心特点

  • 典型发布-订阅模型,一对多联动
  • 观察者可动态订阅/取消订阅
  • 主题与观察者松耦合,互不依赖具体实现
  • 适合事件广播、消息推送场景

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.util.ArrayList;
import java.util.List;

// 主题接口
interface Subject {
    void attach(Observer o);
    void detach(Observer o);
    void notifyObservers();
}

// 观察者接口
interface Observer {
    void update(String message);
}

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

// 具体观察者
class ConcreteObserver implements Observer {
    private String name;
    
    public ConcreteObserver(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        System.out.println(name + " received update: " + message);
    }
}

// 测试
public class ObserverDemo {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        Observer obs1 = new ConcreteObserver("Observer1");
        Observer obs2 = new ConcreteObserver("Observer2");
        
        subject.attach(obs1);
        subject.attach(obs2);
        
        subject.setState("New State");
    }
}

观察者模式-天气预报

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.util.ArrayList;
import java.util.List;

// 观察者接口
interface Observer {
    void update(String weatherInfo);
}

// 主题接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 具体主题类:气象站
class WeatherStation implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String weatherInfo;

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(weatherInfo);
        }
    }

    public void setWeatherInfo(String weatherInfo) {
        this.weatherInfo = weatherInfo;
        notifyObservers();
    }
}

// 具体观察者:手机天气应用
class MobileWeatherApp implements Observer {
    @Override
    public void update(String weatherInfo) {
        System.out.println("手机天气应用收到更新:" + weatherInfo);
    }
}

// 具体观察者:电视台
class TVStation implements Observer {
    @Override
    public void update(String weatherInfo) {
        System.out.println("电视台收到更新:" + weatherInfo);
    }
}

// 客户端类
public class WeatherForecastObserver {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
        MobileWeatherApp mobileApp = new MobileWeatherApp();
        TVStation tvStation = new TVStation();

        weatherStation.registerObserver(mobileApp);
        weatherStation.registerObserver(tvStation);

        weatherStation.setWeatherInfo("今天有雨");
    }
}

8. 状态模式

一、核心模型

现实模型:自动售货机
售货机有待机、投币、出货多种状态;不同状态下同一操作响应不同,状态自动流转。

核心对应:

  • 上下文:自动售货机,持有当前状态
  • 状态接口:统一行为规范
  • 具体状态:待机/投币/出货,各自封装行为
  • 特点:状态驱动行为、消除大量if-else

二、原理描述

将不同状态的行为封装到独立状态类,上下文委托当前状态处理请求;
对象行为随状态自动变化,新增状态无需修改原有上下文代码。

三、核心特点

  • 把状态和行为绑定,逻辑拆分清晰
  • 消除臃肿的if-else状态判断
  • 符合开闭原则,新增状态只加新类
  • 状态流转由状态类自身控制,解耦上下文

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 状态接口
interface State {
    void doAction(Context context);
}

// 具体状态A
class StateA implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("State A handling request, switching to State B");
        context.setState(new StateB());
    }
}

// 具体状态B
class StateB implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("State B handling request, switching to State A");
        context.setState(new StateA());
    }
}

// 上下文类
class Context {
    private State state;
    
    public Context(State state) {
        this.state = state;
    }
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void request() {
        state.doAction(this);
    }
}

// 测试
public class StateDemo {
    public static void main(String[] args) {
        Context context = new Context(new StateA());
        context.request();
        context.request();
    }
}

状态模式-自动售货机

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
// 状态接口
interface VendingMachineState {
    void insertCoin(VendingMachine vendingMachine);
    void selectProduct(VendingMachine vendingMachine);
    void dispenseProduct(VendingMachine vendingMachine);
    void refund(VendingMachine vendingMachine);
}

// 待机状态类
class StandbyState implements VendingMachineState {
    @Override
    public void insertCoin(VendingMachine vendingMachine) {
        System.out.println("硬币已投入,进入投币状态");
        vendingMachine.setState(new CoinInsertedState());
    }
    @Override
    public void selectProduct(VendingMachine vendingMachine) {
        System.out.println("请先投币");
    }
    @Override
    public void dispenseProduct(VendingMachine vendingMachine) {
        System.out.println("请先投币并选择商品");
    }
    @Override
    public void refund(VendingMachine vendingMachine) {
        System.out.println("您还未投币,无需退款");
    }
}

// 投币状态类
class CoinInsertedState implements VendingMachineState {
    @Override
    public void insertCoin(VendingMachine vendingMachine) {
        System.out.println("您已经投过币了,可直接选择商品");
    }
    @Override
    public void selectProduct(VendingMachine vendingMachine) {
        System.out.println("商品已选择,准备出货");
        vendingMachine.setState(new DispensingState());
    }
    @Override
    public void dispenseProduct(VendingMachine vendingMachine) {
        System.out.println("请先选择商品");
    }
    @Override
    public void refund(VendingMachine vendingMachine) {
        System.out.println("硬币已退还,回到待机状态");
        vendingMachine.setState(new StandbyState());
    }
}

// 出货状态类
class DispensingState implements VendingMachineState {
    @Override
    public void insertCoin(VendingMachine vendingMachine) {
        System.out.println("正在出货,请稍等");
    }
    @Override
    public void selectProduct(VendingMachine vendingMachine) {
        System.out.println("正在出货,请稍等");
    }
    @Override
    public void dispenseProduct(VendingMachine vendingMachine) {
        System.out.println("商品已出货,回到待机状态");
        vendingMachine.setState(new StandbyState());
    }
    @Override
    public void refund(VendingMachine vendingMachine) {
        System.out.println("正在出货,无法退款,请稍等");
    }
}

// 上下文类:自动售货机
class VendingMachine {
    private VendingMachineState currentState;

    public VendingMachine() {
        this.currentState = new StandbyState();
    }

    public void setState(VendingMachineState state) {
        this.currentState = state;
    }

    public void insertCoin() {
        currentState.insertCoin(this);
    }
    public void selectProduct() {
        currentState.selectProduct(this);
    }
    public void dispenseProduct() {
        currentState.dispenseProduct(this);
    }
    public void refund() {
        currentState.refund(this);
    }
}

// 客户端类
public class VendingMachineStatePattern {
    public static void main(String[] args) {
        VendingMachine vendingMachine = new VendingMachine();
        vendingMachine.insertCoin();
        vendingMachine.selectProduct();
        vendingMachine.dispenseProduct();
    }
}

9. 策略模式

一、核心模型

现实模型:出行方式选择
出行可切换步行、骑车、公交、打车;每种出行方式是一种独立算法,可随时替换,不改动出行主逻辑。

核心对应:

  • 策略接口:统一算法规范
  • 具体策略:各种出行方式/运算算法
  • 上下文:持有策略、调度执行
  • 特点:算法封装、可动态切换、解耦

二、原理描述

定义一族算法,每个算法封装为独立策略类;
算法可独立于客户端变化,客户端通过上下文动态切换策略,无需写大量条件判断。

三、核心特点

  • 算法统一封装,相互可替换
  • 算法与业务逻辑解耦
  • 新增算法不用改上下文,符合开闭
  • 彻底消除算法选择的if-else

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 策略接口
interface Strategy {
    int doOperation(int num1, int num2);
}

// 加法策略
class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

// 减法策略
class OperationSubtract implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

// 乘法策略
class OperationMultiply implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

// 上下文
class ContextStrategy {
    private Strategy strategy;
    
    public ContextStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

// 测试
public class StrategyDemo {
    public static void main(String[] args) {
        ContextStrategy context = new ContextStrategy(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
        
        context = new ContextStrategy(new OperationSubtract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
        
        context = new ContextStrategy(new OperationMultiply());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

策略模式-出行方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 策略接口
interface TravelStrategy {
    void travel();
}

// 步行策略
class WalkStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("选择步行出行,欣赏沿途风景");
    }
}

// 骑行策略
class BikeStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("选择骑自行车出行,灵活便捷");
    }
}

// 公交策略
class BusStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("选择乘坐公交车出行,经济实惠");
    }
}

// 打车策略
class TaxiStrategy implements TravelStrategy {
    @Override
    public void travel() {
        System.out.println("选择打车出行,快速高效");
    }
}

// 上下文类
class TravelContext {
    private TravelStrategy strategy;

    public TravelContext(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(TravelStrategy strategy) {
        this.strategy = strategy;
    }

    public void executeTravel() {
        strategy.travel();
    }
}

// 客户端类
public class TravelStrategyPattern {
    public static void main(String[] args) {
        TravelContext context = new TravelContext(new WalkStrategy());
        context.executeTravel();

        context.setStrategy(new BikeStrategy());
        context.executeTravel();

        context.setStrategy(new BusStrategy());
        context.executeTravel();

        context.setStrategy(new TaxiStrategy());
        context.executeTravel();
    }
}

10. 模板方法模式

一、核心模型

现实模型:制作咖啡和茶
制作饮品整体流程固定:烧水→备料→冲泡→加配料;
流程骨架在父类固定,可变步骤定义为抽象方法,由子类实现不同细节。

核心对应:

  • 抽象模板类:定义固定流程骨架
  • 模板方法:final 禁止重写,保证流程顺序
  • 抽象步骤:由子类实现个性化逻辑
  • 特点:骨架固定、步骤可扩展、复用流程

二、原理描述

在抽象类中定义算法流程骨架,固定执行顺序;
将可变步骤抽象为方法,延迟到子类实现,不改变整体流程即可定制不同步骤逻辑。

三、核心特点

  • 流程骨架统一复用,减少重复代码
  • 模板方法加 final,防止子类篡改流程
  • 可变步骤由子类实现,灵活扩展
  • 反向控制:父类调用子类方法

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 抽象类定义模板方法
abstract class Game {
    // 模板方法:固定算法骨架
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
    
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();
}

// 具体子类
class FootballGame extends Game {
    @Override
    void initialize() {
        System.out.println("Football Game Initialized! Start playing.");
    }
    @Override
    void startPlay() {
        System.out.println("Football Game Started. Enjoy the game!");
    }
    @Override
    void endPlay() {
        System.out.println("Football Game Finished!");
    }
}

// 测试
public class TemplateMethodDemo {
    public static void main(String[] args) {
        Game game = new FootballGame();
        game.play();
    }
}

模板方法-泡茶咖啡

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 抽象模板类:制作饮品
abstract class BeverageMaker {
    // 模板方法,固定流程
    final void makeBeverage() {
        boilWater();
        prepareIngredients();
        brew();
        addCondiments();
        System.out.println("一杯美味的饮品制作完成!");
    }

    // 通用固定步骤
    void boilWater() {
        System.out.println("正在烧水...");
    }

    // 抽象可变步骤
    abstract void prepareIngredients();
    abstract void brew();
    abstract void addCondiments();
}

// 制作咖啡子类
class CoffeeMaker extends BeverageMaker {
    @Override
    void prepareIngredients() {
        System.out.println("准备咖啡豆并研磨...");
    }
    @Override
    void brew() {
        System.out.println("用研磨好的咖啡豆冲泡咖啡...");
    }
    @Override
    void addCondiments() {
        System.out.println("添加牛奶和糖...");
    }
}

// 制作茶子类
class TeaMaker extends BeverageMaker {
    @Override
    void prepareIngredients() {
        System.out.println("准备茶叶...");
    }
    @Override
    void brew() {
        System.out.println("用热水浸泡茶叶...");
    }
    @Override
    void addCondiments() {
        System.out.println("添加柠檬片...");
    }
}

// 客户端类
public class TemplateMethodPatternExample {
    public static void main(String[] args) {
        BeverageMaker coffeeMaker = new CoffeeMaker();
        coffeeMaker.makeBeverage();

        System.out.println("------------------");

        BeverageMaker teaMaker = new TeaMaker();
        teaMaker.makeBeverage();
    }
}

11. 访问者模式

一、核心模型

现实模型:动物园动物体检
动物园有狮子、猴子、大象等动物;新增体检项目(健康检查、口腔检查)不用改动物类,新增访问者即可。

核心对应:

  • 元素:动物类,提供接收访问者入口
  • 访问者:体检类型,重载不同动物访问方法
  • 对象结构:动物园,管理所有元素
  • 特点:在不修改元素类的前提下新增操作

二、原理描述

作用于元素的操作抽离为访问者,元素只提供接收访问者的入口;
新增操作只需新增访问者类,无需修改原有元素结构,适合数据结构固定、操作频繁变化的场景。

三、核心特点

  • 元素类稳定,可动态新增操作
  • 把相关操作集中到一个访问者类中
  • 适合数据结构固定、行为易变场景
  • 缺点:新增元素需修改所有访问者,违背开闭

四、Java 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.util.ArrayList;
import java.util.List;

// 访问者接口
interface Visitor {
    void visit(ElementA element);
    void visit(ElementB element);
}

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
class ElementA implements Element {
    public void operationA() {
        System.out.println("ElementA operation");
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素B
class ElementB implements Element {
    public void operationB() {
        System.out.println("ElementB operation");
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体访问者
class ConcreteVisitor implements Visitor {
    @Override
    public void visit(ElementA element) {
        System.out.println("Visitor processing ElementA");
        element.operationA();
    }
    @Override
    public void visit(ElementB element) {
        System.out.println("Visitor processing ElementB");
        element.operationB();
    }
}

// 对象结构
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();
    
    public void addElement(Element element) {
        elements.add(element);
    }
    
    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 测试
public class VisitorDemo {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();
        structure.addElement(new ElementA());
        structure.addElement(new ElementB());
        
        Visitor visitor = new ConcreteVisitor();
        structure.accept(visitor);
    }
}

访问者模式-动物园

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
import java.util.ArrayList;
import java.util.List;

// 动物元素接口
interface Animal {
    void accept(Veterinarian visitor);
}

// 狮子
class Lion implements Animal {
    @Override
    public void accept(Veterinarian visitor) {
        visitor.visit(this);
    }
}

// 猴子
class Monkey implements Animal {
    @Override
    public void accept(Veterinarian visitor) {
        visitor.visit(this);
    }
}

// 大象
class Elephant implements Animal {
    @Override
    public void accept(Veterinarian visitor) {
        visitor.visit(this);
    }
}

// 访问者接口:兽医
interface Veterinarian {
    void visit(Lion lion);
    void visit(Monkey monkey);
    void visit(Elephant elephant);
}

// 健康检查访问者
class HealthCheckVeterinarian implements Veterinarian {
    @Override
    public void visit(Lion lion) {
        System.out.println("对狮子进行健康检查,检查肌肉力量。");
    }
    @Override
    public void visit(Monkey monkey) {
        System.out.println("对猴子进行健康检查,检查灵活性。");
    }
    @Override
    public void visit(Elephant elephant) {
        System.out.println("对大象进行健康检查,检查心脏功能。");
    }
}

// 口腔检查访问者
class OralCheckVeterinarian implements Veterinarian {
    @Override
    public void visit(Lion lion) {
        System.out.println("对狮子进行口腔检查,查看牙齿磨损情况。");
    }
    @Override
    public void visit(Monkey monkey) {
        System.out.println("对猴子进行口腔检查,查看牙龈健康。");
    }
    @Override
    public void visit(Elephant elephant) {
        System.out.println("对大象进行口腔检查,检查象牙状况。");
    }
}

// 对象结构:动物园
class Zoo {
    private List<Animal> animals = new ArrayList<>();

    public void addAnimal(Animal animal) {
        animals.add(animal);
    }

    public void accept(Veterinarian visitor) {
        for (Animal animal : animals) {
            animal.accept(visitor);
        }
    }
}

// 客户端
public class ZooVisitorPattern {
    public static void main(String[] args) {
        Zoo zoo = new Zoo();
        zoo.addAnimal(new Lion());
        zoo.addAnimal(new Monkey());
        zoo.addAnimal(new Elephant());

        HealthCheckVeterinarian healthCheck = new HealthCheckVeterinarian();
        zoo.accept(healthCheck);

        System.out.println("----------------------");

        OralCheckVeterinarian oralCheck = new OralCheckVeterinarian();
        zoo.accept(oralCheck);
    }
}

总结

以上就是常见的 23 种设计模式,对加深封装、继承、多态、接口的理解帮助很多。这些模式都是建立在熟练掌握基础的前提下。