---
dir: 
  order: 5
---


# 设计模式

## 单例模式---创建型

### 双重检查锁定（DCL）

```java
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {
        // 构造函数私有化
    }

    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
```

### 静态内部类方式

利用 **静态内部类**（饿汉式）的特性来实现懒汉模式，并且可以保证线程安全。这种方式只有在调用 `getInstance()` 时才会加载内部类，从而实现懒加载。

```java
public class Singleton {
    private Singleton() {
        // 构造函数私有化
    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
```

### 饿汉模式

**饿汉模式**（Eager Initialization）是单例模式的一种实现方式，在该方式中，单例实例在类加载时就已经创建完成，而不是在首次使用时才创建。换句话说，**饿汉模式**
的单例实例在类被加载时就会立即初始化，确保了单例模式的唯一性。

```java
public class Singleton {

    // 在类加载时就初始化单例对象
    private static final Singleton INSTANCE = new Singleton();

    // 私有构造函数，防止外部通过 new 创建实例
    private Singleton() {
    }

    // 提供全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
```

### 枚举类型实现

最推荐的方式！！！当你不需要懒加载或延迟初始化时，使用枚举实现单例模式是最理想的选择。

```java
public enum Singleton {

    // 唯一实例
    INSTANCE;

    // 可以添加其他的方法
    public void someMethod() {
        System.out.println("This is a singleton instance method.");
    }
}
```

## 工厂模式---创建型

### 工厂模式（Factory Pattern）介绍

工厂模式属于创建型设计模式，主要用于通过定义一个接口来创建对象，但让子类决定实例化哪一个类。通过这种方式，工厂模式将对象的创建与使用分离，从而解耦了客户端与具体类的依赖关系。

工厂模式的核心思想是：**让子类决定具体要创建哪一个产品，而不是直接在客户端代码中硬编码要使用哪个类**。

### 工厂模式的主要角色

1. **产品接口（Product）**：通常是一个接口或者抽象类，定义了具体产品的公共方法。
2. **具体产品（Concrete Product）**：实现了产品接口的具体类，代表不同的产品。
3. **工厂接口（Creator）**：通常是一个抽象类或接口，定义了一个工厂方法用于创建产品。
4. **具体工厂（Concrete Creator）**：实现了工厂接口的具体类，负责创建具体的产品对象。

### 工厂模式的类型

1. **简单工厂模式（Simple Factory）**：通过工厂类中的一个方法，根据传入的参数决定返回哪种具体的产品对象。
2. **工厂方法模式（Factory Method）**：通过一个工厂接口或者抽象类来定义创建产品的工厂方法，让子类决定创建哪个具体产品。
3. **抽象工厂模式（Abstract Factory）**：提供一个创建一系列相关或相互依赖对象的接口，而无需指定具体类。

### 简单工厂模式示例（Java）

```java
// 产品接口
public interface Product {
    void create();
}

// 具体产品A
public class ProductA implements Product {
    @Override
    public void create() {
        System.out.println("Product A created.");
    }
}

// 具体产品B
public class ProductB implements Product {
    @Override
    public void create() {
        System.out.println("Product B created.");
    }
}

// 工厂类
public class ProductFactory {
    // 简单工厂方法，根据输入参数创建不同的产品
    public static Product createProduct(String productType) {
        if ("A".equals(productType)) {
            return new ProductA();
        } else if ("B".equals(productType)) {
            return new ProductB();
        }
        throw new IllegalArgumentException("Unknown product type");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Product productA = ProductFactory.createProduct("A");
        productA.create();

        Product productB = ProductFactory.createProduct("B");
        productB.create();
    }
}
```

### 优点

1. **降低耦合度**：工厂模式将对象的创建过程与使用过程分开，客户端不需要了解具体的创建过程，从而降低了耦合度。
2. **易于扩展**：可以通过新增具体产品类和工厂方法来扩展系统，不需要修改现有代码，符合开闭原则（OCP）。
3. **提高代码的可维护性**：当需要修改创建产品的逻辑时，只需修改工厂类，不影响客户端代码。

### 缺点

1. **增加类的数量**：引入了工厂类、产品接口和多个具体产品类，可能导致类的数量增加，系统变得复杂。
2. **难以理解和维护**：对于一些简单的应用程序，使用工厂模式可能会使得设计过于复杂，反而增加了理解和维护的难度。

## 观察者模式---行为型

观察者有四个角色，观察者（Observe）和具体观察者（Concrete Observe）、主题（Subject）和具体主题（Concrete Subject），具体观察者和具体主题可以多个。

- **Subject（主题）**：维护观察者列表，提供添加、删除和通知观察者的方法。
- **Observer（观察者）**：定义更新接口，供主题通知时调用。
- **ConcreteObserver（具体观察者）**：实现更新接口，执行具体操作。

![img](./images/1739543242386-d095f0de-d731-4412-b951-280160565fa6.png)

### 简单示例

其中主题中有3个方法，添加（或者理解成注册都可以）、移出、通知，差不多都是这三个方法，其中添加可以理解成注册加入总之是往数组中添加观察者。

#### 代码实现

```java
public class ObserverDemo {
    public static void main(String[] args) {
        // 定义的主题
        News news = new News();

        // 观察者
        SisterObserver sisterObserver = new SisterObserver();
        GirlfriendObserver girlfriendObserver = new GirlfriendObserver();

        // 添加观察者
        news.addObserver(sisterObserver);
        news.notifyObservers("添加了妹妹");

        System.out.println("\n-----------------分割线-----------------\n");

        // 添加女朋友
        news.addObserver(girlfriendObserver);
        news.notifyObservers("添加了女朋友");

        System.out.println("\n-----------------分割线-----------------\n");
        news.removeObserver(girlfriendObserver);
        news.notifyObservers("需要和妹妹说点悄悄话，将女朋友移除了，这时女朋友听不见我们说话。。。");
    }

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

    // 主题接口
    interface Subject {
        void addObserver(Observer observer);

        void removeObserver(Observer observer);

        void notifyObservers(String message);
    }

    // 妹妹观察者
    static class SisterObserver implements Observer {
        @Override
        public void update(String message) {
            System.out.println("SisterObserver 接受到消息：" + message);
        }
    }

    // 女朋友观察者
    static class GirlfriendObserver implements Observer {
        @Override
        public void update(String message) {
            System.out.println("GirlfriendObserver 接受到消息：" + message);
        }
    }

    // 主题类
    static class News implements Subject {

        private final List<Observer> observerList = new ArrayList<>();

        @Override
        public void addObserver(Observer observer) {
            observerList.add(observer);
        }

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

        @Override
        public void notifyObservers(String message) {
            for (Observer observer : observerList) {
                observer.update(message);
            }
        }
    }
}
```

#### 运行结果：

```java
SisterObserver 接受到消息：添加了妹妹

-----------------分割线-----------------

SisterObserver 接受到消息：添加了女朋友
GirlfriendObserver 接受到消息：添加了女朋友

-----------------分割线-----------------

SisterObserver 接受到消息：需要和妹妹说点悄悄话，将女朋友移除了，这时女朋友听不见我们说话。。。
```

## 策略模式---行为型

策略模式广泛应用于支付、计算、文件压缩、登录等场景，尤其是在游戏中，如王者荣耀和PUBG的角色处理。值得注意的是，在实际开发中，一种业务场景可能会同时使用多种设计模式，因此，下面的介绍仅为简化并专注于策略模式的核心概念。

1. **Context（上下文）**：持有一个策略对象的引用，通过接口调用具体策略。
2. **Strategy（策略）**：定义所有支持的算法的公共接口。
3. **ConcreteStrategy（具体策略）**：实现策略接口，提供具体算法。

其中，`Context` 的概念较为抽象，通常用来持有策略并在运行时动态地切换策略。

![img](./images/1739543251619-bf2f7654-ccba-4ceb-939f-ac0653da1051.png)

### 简单示例

#### 代码实现

策略模式的实现并不复杂，主要是定义三个角色：抽象策略、具体策略和上下文。为了更清晰地展示，我定义了两个具体策略，每个策略执行不同的操作。然后将策略放入上下文中，最终通过上下文来执行具体策略的方法。

```java
public class BaseStrategy {

    public static void main(String[] args) {
        // 创建具体策略
        ConcreteStrategy1 concreteStrategy1 = new ConcreteStrategy1();
        ConcreteStrategy2 concreteStrategy2 = new ConcreteStrategy2();

        // 通过上下文执行策略
        new Context(concreteStrategy1).doIt();
        new Context(concreteStrategy2).doIt();
    }

    // 抽象策略接口
    public interface Strategy {
        /**
         * 执行策略方法
         */
        void method();
    }

    // 具体策略实现1
    public static class ConcreteStrategy1 implements Strategy {
        @Override
        public void method() {
            System.out.println("执行具体策略1...");
        }
    }

    // 具体策略实现2
    public static class ConcreteStrategy2 implements Strategy {
        @Override
        public void method() {
            System.out.println("执行具体策略2...");
        }
    }

    // 上下文类，持有策略并执行
    public static class Context {
        private final Strategy strategy;

        public Context(Strategy strategy) {
            this.strategy = strategy;
        }

        /**
         * 执行策略的方法
         */
        public void doIt() {
            strategy.method();
        }
    }
}
```

#### 执行结果：

```java
执行具体策略1...
执行具体策略2...
```

### 示例-游戏角色

需要制作的游戏角色业务需求，基础角色是其他角色的抽象，包括国王、王后、骑士、士兵等，武器是一个接口所有武器都实现这个接口，切换武器（武器有主武器和副武器）可以调用`setPrimaryWeapon`和`setSubWeapon`。

![img](./images/1739543262730-f61ab1b7-5875-4fd3-8437-8458d48e2d83.png)

#### 代码实现

```java
public class GameCharacter {
    public static void main(String[] args) {
        Character soldier = new Soldier();
        soldier.fight();

        Character king = new King();
        king.setPrimaryWeapon(new AxeWeapon());
        king.fight();
    }

    // 武器接口
    interface Weapon {
        String function();
    }

    // 各种武器实现
    public static class SwordWeapon implements Weapon {
        @Override
        public String function() {
            return "⚔️ ⚔️ ⚔️";
        }
    }

    public static class AxeWeapon implements Weapon {
        @Override
        public String function() {
            return "🪓 🪓 🪓";
        }
    }

    public static class KnifeWeapon implements Weapon {
        @Override
        public String function() {
            return "🔪 🔪 🔪";
        }
    }

    // 抽象角色类
    public abstract static class Character {
        String name;
        @Setter
        private Weapon primaryWeapon;
        @Setter
        private Weapon subWeapon;

        public Character(String name) {
            this.name = name;
            // 默认武器配置
            this.primaryWeapon = new SwordWeapon();
            this.subWeapon = new KnifeWeapon();
        }

        void fight() {
            if (primaryWeapon != null && subWeapon != null) {
                String primary = primaryWeapon.function();
                String sub = subWeapon.function();
                System.out.println(name + "：" + primary + "和" + sub);
            } else {
                System.out.println(name + "没有武器！");
            }
        }
    }

    // 国王角色
    public static class King extends Character {
        public King() {
            super("King");
            setPrimaryWeapon(new SwordWeapon());
            setSubWeapon(new KnifeWeapon());
        }
    }

    // 士兵角色
    public static class Soldier extends Character {
        public Soldier() {
            super("Soldier");
            setPrimaryWeapon(new AxeWeapon());
            setSubWeapon(new SwordWeapon());
        }
    }
}
```

#### 运行结果：

```java
Soldier：🪓 🪓 🪓和⚔️ ⚔️ ⚔️
King：🪓 🪓 🪓和🔪 🔪 🔪
```

## 装饰者模式---结构型

![img](./images/1739543272234-84db0862-68a4-4d92-b120-35c92090284a.png)

- 抽象组件：一般是最原始、最基础的对象。
- 具体组件：一般是最原始最基础的实现对象，可以有多个（只是数量不多），可以大致看下`InputStream`UML结构图。
- 装饰角色：继承或者实现**抽象组件**这是最关键的地方。
- 具体装饰角色：可以有多个实现或者继承**装饰角色**。

### 简单示例

需要做一个抽象的相机功能，相机包含拍照功能（这是肯定的），之后随着业务需求要求相机有美颜功能，在这之后还要有滤镜功能，客户还需要延迟摄影功能。

#### 代码实现

1. 需要定义根组件（Component）
2. 制作最原始的拍照功能，实现根组件
3. 制作延迟摄影，实现根组件
4. 作为相机之外的功能（美颜），需要定义装饰角色方便为以后的组件进行扩展
5. 继承或者实现（装饰者角色），完成美颜
6. 继承或者实现（装饰者角色），完成滤镜

```java
public class CameraDemo {
    public static void main(String[] args) {
        TakePhotoCamera takePhotoCamera = new TakePhotoCamera();
        takePhotoCamera.operation();

        System.out.println("\n-----------------分割线-----------------\n");

        BeautyCamera beautyCamera = new BeautyCamera(takePhotoCamera);
        beautyCamera.operation();

        System.out.println("\n-----------------分割线-----------------\n");

        FilterCamera filterCamera = new FilterCamera(beautyCamera);
        filterCamera.operation();

        System.out.println("\n-----------------分割线-----------------\n");

        TimerCamera timerCamera = new TimerCamera();
        timerCamera.setTime(2);
        timerCamera.operation();
        filterCamera = new FilterCamera(beautyCamera);
        filterCamera.operation();
    }

    // 相机功能
    interface Camera {

        /**
         * 相机操作
         */
        void operation();
    }

    // 相机装饰者角色
    static abstract class CameraDecorator implements Camera {
        Camera camera;

        public CameraDecorator(Camera camera) {
            this.camera = camera;
        }
    }

    // 相机拍照
    static class TakePhotoCamera implements Camera {

        /**
         * 相机操作
         */
        @Override
        public void operation() {
            System.out.println("相机拍照。。。");
        }
    }

    // 相机功能
    static class BeautyCamera extends CameraDecorator {

        public BeautyCamera(Camera camera) {
            super(camera);
        }

        /**
         * 相机操作
         */
        @Override
        public void operation() {
            camera.operation();
            System.out.println("美颜功能。。。");
        }
    }

    // 滤镜效果
    static class FilterCamera extends CameraDecorator {

        public FilterCamera(Camera camera) {
            super(camera);
        }

        /**
         * 相机操作
         */
        @Override
        public void operation() {
            camera.operation();
            System.out.println("滤镜效果。。。");
        }
    }

    // 实现相机延迟功能
    @Setter
    static class TimerCamera implements Camera {

        // 延迟时间
        private Integer time = 0;

        /**
         * 相机操作
         */
        @Override
        public void operation() {
            System.out.println("开始拍照，延迟时间：" + time + "s");
            try {
                Thread.sleep(time * 1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
```

#### 运行结果：

```java
相机拍照。。。

-----------------分割线-----------------

相机拍照。。。
美颜功能。。。

-----------------分割线-----------------

相机拍照。。。
美颜功能。。。
滤镜效果。。。

-----------------分割线-----------------

开始拍照，延迟时间：2s
相机拍照。。。
美颜功能。。。
滤镜效果。。。
```

## 适配器模式---结构型

在生活中，有时需要将380V三相电转成220V，这时候需要变压器，当然也有三相电转两相电接法，我们可以使用代码模拟这个操作 。

![img](./images/1739543285861-d95f968f-0a5e-4a9d-ba80-ea61907afd3f.png)

抽象适配者角色（Abstract Adapter）、适配者角色（Adapter）、目标角色（Target）

#### 示例代码

```java
public class Adapter1 {
    public static void main(String[] args) {
        PowerAdapter powerAdapter = new PowerAdapter();
        Integer integer = powerAdapter.output220V();

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

        PowerAdapter powerAdapter1 = new PowerAdapter();
        powerAdapter1.output220V();
        Integer i = powerAdapter1.output380V();
    }

    // 电压输出
    interface PowerTarget {
        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        Integer output220V();
    }

    static class PowerAdapter extends Power implements PowerTarget {

        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        @Override
        public Integer output220V() {
            Integer output = super.getOutput();
            System.out.println("变压器交流" + output + "v转220v三相电变两项电。。。");

            double adapter = new Random().nextDouble(1.64, 1.72);
            Integer newOutput = (int) (output / adapter);
            System.out.println("变压器转换完成：电压输出为：" + newOutput);

            return newOutput;
        }
    }

    @Data
    static class Power {
        private Integer output = 380;

        public Integer output380V() {
            System.out.println("输出电压：" + output);
            return output;
        }
    }
}
```

#### 运行结果：

```java
变压器交流380v转220v三相电变两项电。。。
变压器转换完成：电压输出为：224
----------------
变压器交流380v转220v三相电变两项电。。。
变压器转换完成：电压输出为：224
输出电压：380
```

## 模板方法模式---行为型

将定义好的按步骤执行的内容进行封装，模板方法是比较单间的设计模式，是代码复用的基本技术，在类库中尤其重要，遵循：“抽象类应当拥有尽可能多的可能性，应当拥有尽可能少的数据”。

比如做一些比较固定的事情（支付流程处理），但是其中几项内容可能会发生改变。

![img](./images/1739543298433-bb44826b-b586-4181-a5fc-e33c370f4220.png)

抽象类（Abstract Class）、具体类（Concrete Class）。

### 简单示例

#### 示例代码

```java
public class PaymentProcess {
    public static void main(String[] args) {
        ConcretePaymentProcess concretePaymentProcess = new ConcretePaymentProcess();
        concretePaymentProcess.startProcess();
    }

    // 抽象模板方法
    static abstract class AbstractPaymentProcess {

        /**
         * 开始流程
         */
        public void startProcess() {
            authenticationUser();
            checkBalance();
            executePayment();
            returnPayment();
        }

        /**
         * 验证用户身份
         */
        private void authenticationUser() {
            System.out.println("验证用户身份。。。");
        }

        /**
         * 检查余额
         */
        public abstract void checkBalance();

        /**
         * 执行支付
         */
        private void executePayment() {
            System.out.println("执行支付。。。");
        }

        /**
         * 返回支付结果
         */
        public abstract void returnPayment();
    }

    static class ConcretePaymentProcess extends AbstractPaymentProcess {

        /**
         * 检查余额
         */
        @Override
        public void checkBalance() {
            System.out.println("检查完成，我的余额还有：1999亿元");
        }

        /**
         * 返回支付结果
         */
        @Override
        public void returnPayment() {
            System.out.println("支付成功，我的余额还有：1994亿元");
        }
    }
}
```

#### 运行结果：

```java
验证用户身份。。。
检查完成，我的余额还有：1999亿元
执行支付。。。
支付成功，我的余额还有：1994亿元
```

## 建造者模式

使用SpringBoot的插件---`lombok`，`@Builder`就是。

![img](./images/1739543307764-71a91d00-a7d3-48ce-8c43-24cdcefaefc2.png)

### 简单示例

比如我们要构建一个复杂的 `Computer`（计算机）对象。我们可以定义一个 `ComputerBuilder`，它将按顺序设置计算机的 CPU、内存、硬盘等组件，最后得到一个完整的 `Computer` 对象。

#### 代码示例

```java
public class CommandDemo {
    public static void main(String[] args) {
        ConcreteLowComputerBuilder concreteLowComputerBuilder = new ConcreteLowComputerBuilder();
        Director director = new Director(concreteLowComputerBuilder);
        director.constructComputer();
        System.out.println(concreteLowComputerBuilder.getComputer());

        System.out.println("\n-----------------分割线-----------------\n");
        
        ConcreteHighComputerBuilder concreteHighComputerBuilder = new ConcreteHighComputerBuilder();
        director = new Director(concreteHighComputerBuilder);
        director.constructComputer();
        System.out.println(concreteHighComputerBuilder.getComputer());
    }

    // 构建产品接口
    interface ComputerBuilder {

        /**
         * 构建 CPU 方法
         */
        void buildCPU();

        /**
         * 构建 RAM 方法
         */
        void buildRAM();

        /**
         * 构建 磁盘 方法
         */
        void buildHardDrive();

        /**
         * 返回产品
         *
         * @return Computer
         */
        Computer getComputer();
    }

    // 产品类
    @Data
    static class Computer {
        private String CPU;
        private String RAM;
        private String hardDrive;
    }

    // 构建低端产品
    static class ConcreteLowComputerBuilder implements ComputerBuilder {
        private final Computer computer = new Computer();

        /**
         * 构建 CPU 方法
         */
        @Override
        public void buildCPU() {
            computer.setCPU("Low CPU");
        }

        /**
         * 构建 RAM 方法
         */
        @Override
        public void buildRAM() {
            computer.setRAM("Low RAM");
        }

        /**
         * 构建 磁盘 方法
         */
        @Override
        public void buildHardDrive() {
            computer.setHardDrive("Low Driver");
        }

        /**
         * 返回产品
         *
         * @return Computer
         */
        @Override
        public Computer getComputer() {
            return computer;
        }
    }

    // 构建高端产品
    static class ConcreteHighComputerBuilder implements ComputerBuilder {
        private final Computer computer = new Computer();

        /**
         * 构建 CPU 方法
         */
        @Override
        public void buildCPU() {
            computer.setCPU("High CPU");
        }

        /**
         * 构建 RAM 方法
         */
        @Override
        public void buildRAM() {
            computer.setRAM("High RAM");
        }

        /**
         * 构建 磁盘 方法
         */
        @Override
        public void buildHardDrive() {
            computer.setHardDrive("High Driver");
        }

        /**
         * 返回产品
         *
         * @return Computer
         */
        @Override
        public Computer getComputer() {
            return computer;
        }
    }

    // 构建者
    public static class Director {
        private final ComputerBuilder builder;

        public Director(ComputerBuilder builder) {
            this.builder = builder;
        }

        public void constructComputer() {
            builder.buildCPU();
            builder.buildRAM();
            builder.buildHardDrive();
        }
    }
}
```

#### 运行结果：

```java
CommandDemo.Computer(CPU=Low CPU, RAM=Low RAM, hardDrive=Low Driver)

-----------------分割线-----------------

CommandDemo.Computer(CPU=High CPU, RAM=High RAM, hardDrive=High Driver)
```

## 代理模式---结构型

### 静态代理-1

![img](./images/1739543321967-fd543d91-6075-46d2-95ac-e3b0460b1ccd.png)

如果是静态代理，做Java开发几乎都在用，就是抽象接口和实现，比如：`UserService`之后`UserServiceImpl`实现`UserService`，就是这个，之后使用`UserService`进行调用实现中的方法。

### 静态代理-2

![img](./images/1739543326373-78624d46-eda6-4c48-93ef-9ab280732bd5.png)

#### 示例代码

```java
public class Proxy {
    public static void main(String[] args) {
        UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
        proxy.saveUser();
        proxy.findUser(1L);
    }

    interface UserService {

        /**
         * 保存用户
         */
        void saveUser();

        /**
         * 查找用户
         */
        Object findUser(Long id);
    }

    static class UserServiceImpl implements UserService {

        /**
         * 保存用户
         */
        @Override
        public void saveUser() {
            System.out.println("保存用户");
        }

        /**
         * 查找用户
         *
         * @param id id
         */
        @Override
        public Object findUser(Long id) {
            System.out.println("查找用户");
            return "User{name:'代理'}";
        }
    }

    static class UserServiceProxy implements UserService {

        private final UserService userService;

        public UserServiceProxy(UserService userService) {
            this.userService = userService;
        }

        /**
         * 保存用户
         */
        @Override
        public void saveUser() {
            userService.saveUser();
        }

        /**
         * 查找用户
         *
         * @param id id
         */
        @Override
        public Object findUser(Long id) {
            return userService.findUser(id);
        }
    }
}
```

#### 运行结果：

```java
保存用户
查找用户
```

## 原型模式---创建型

![img](./images/1739543335707-9996b910-b915-41e9-989e-2e470ce3ff43.png)

需要三个角色：抽象原型类（Abstract Prototype）、具体原型类（Concrete Prototype）、访问类（Client）

### 简单示例

提示：需要做深克隆，当类中还存在另一个类时

#### 错误示例代码

当我们对school对象进行设置时，对`resume1`进行设置结果`resume`也发生了改变。需要修改`Resume`类中的`clone`方法

```java
public class Prototype {
    public static void main(String[] args) {
        Resume resume = new Resume();
        resume.name = "Bunny";
        resume.position = "架构师";
        resume.salary = 15000;

        School school = new School();
        school.schoolName = "江南大学";
        school.time = "2025年2月2日21:38:07";
        resume.school = school;
        System.out.println(resume);

        Resume resume1 = resume.clone();
        resume1.salary = 19000;
        resume1.school.schoolName = "清华大学";
        System.out.println(resume1);

        Resume resume2 = resume.clone();
        resume2.salary = 20000;
        System.out.println(resume2);

        System.out.println(resume1 == resume2);// false
        System.out.println(resume1.school == resume2.school);// true
    }

    @Data
    static class Resume implements Cloneable {
        private String name;
        private String position;
        private Integer salary;
        private School school;

        @Override
        public Resume clone() {
            try {
                return (Resume) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new AssertionError();
            }
        }
    }

    @Data
    static class School implements Cloneable {
        private String schoolName;
        private String time;

        @Override
        public School clone() {
            try {
                return (School) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new AssertionError();
            }
        }
    }
}
```

#### 运行结果：

```java
Prototype.Resume(name=Bunny, position=架构师, salary=15000, school=Prototype.School(schoolName=江南大学, time=2025年2月2日21:38:07))
Prototype.Resume(name=Bunny, position=架构师, salary=19000, school=Prototype.School(schoolName=清华大学, time=2025年2月2日21:38:07))
Prototype.Resume(name=Bunny, position=架构师, salary=20000, school=Prototype.School(schoolName=清华大学, time=2025年2月2日21:38:07))
false
true
```

#### 正确示例代码

##### 修改`conle`

```java
@Data
static class Resume implements Cloneable {
    private String name;
    private String position;
    private Integer salary;
    private School school;

    @Override
    public Resume clone() {
        Resume resume = null;
        try {
            resume = (Resume) super.clone();
            if (school != null) {
                resume.school = school.clone();
            }
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }

        return resume;
    }
}
```

##### 示例

```java
public class Prototype {
    public static void main(String[] args) {
        Resume resume = new Resume();
        resume.name = "Bunny";
        resume.position = "架构师";
        resume.salary = 15000;

        School school = new School();
        school.schoolName = "江南大学";
        school.time = "2025年2月2日21:38:07";
        resume.school = school;
        System.out.println(resume);

        Resume resume1 = resume.clone();
        resume1.salary = 19000;
        resume1.school.schoolName = "清华大学";
        System.out.println(resume1);

        Resume resume2 = resume.clone();
        resume2.salary = 20000;
        System.out.println(resume2);

        System.out.println(resume1 == resume2);// false
        System.out.println(resume1.school == resume2.school);// false
    }

    @Data
    static class Resume implements Cloneable {
        private String name;
        private String position;
        private Integer salary;
        private School school;

        @Override
        public Resume clone() {
            Resume resume = null;
            try {
                resume = (Resume) super.clone();
                if (school != null) {
                    resume.school = school.clone();
                }
            } catch (CloneNotSupportedException e) {
                throw new AssertionError();
            }

            return resume;
        }
    }

    @Data
    static class School implements Cloneable {
        private String schoolName;
        private String time;

        @Override
        public School clone() {
            try {
                return (School) super.clone();
            } catch (CloneNotSupportedException e) {
                throw new AssertionError();
            }
        }
    }
}
```

#### 运行结果：

```java
Prototype.Resume(name=Bunny, position=架构师, salary=15000, school=Prototype.School(schoolName=江南大学, time=2025年2月2日21:38:07))
Prototype.Resume(name=Bunny, position=架构师, salary=19000, school=Prototype.School(schoolName=清华大学, time=2025年2月2日21:38:07))
Prototype.Resume(name=Bunny, position=架构师, salary=20000, school=Prototype.School(schoolName=江南大学, time=2025年2月2日21:38:07))
false
false
```

## 外观模式---结构型

有点类似网址导航的思想，比如有很多零散的东西（网址）但是每次我们想用的时候需要寻找这些网址，如果有个网址大全讲这些网址封装我们寻找会方便很多。

再或者，我们每天看天气，需要打开手机点开天气应用、熄屏；如果我们将这些东西封装成单独的指令会简化我们平时的行为，比如写个脚本执行上面的事情。

主要角色：门面角色（Facade）、子系统角色（Sub System）、客户角色（Client）。

![img](./images/1739543349334-16d8337f-1a34-4242-869b-bd0acc62f658.png)

### 简单实现

#### 示例代码

```java
public class Facade {
    public static void main(String[] args) {
        DeviceFacade deviceFacade = new DeviceFacade();
        // 查看
        deviceFacade.on();

        // 看完关闭
        deviceFacade.off();
    }

    // 子系统-手机
    static class SubSystemIPhone {
        public void on() {
            System.out.println("打开手机。。。");
        }

        public void off() {
            System.out.println("关闭手机。。。");
        }
    }

    // 子系统-天气
    static class SubSystemWeather {
        public void on() {
            System.out.println("打开天气。。。");
        }

        public void off() {
            System.out.println("关闭天气。。。");
        }
    }

    // 门面
    static class DeviceFacade {
        // 也可以作为参数传递，如果没有别的实现类，直接在内部初始化会使使用者更简单
        SubSystemIPhone subSystemIPhone = new SubSystemIPhone();
        SubSystemWeather subSystemWeather = new SubSystemWeather();

        public void on() {
            subSystemIPhone.on();
            subSystemWeather.on();
        }

        public void off() {
            subSystemWeather.off();
            subSystemIPhone.off();
        }
    }
}
```

#### 运行结果：

```java
打开手机。。。
打开天气。。。
关闭天气。。。
关闭手机。。。
```

### 对象适配器

![img](./images/1739543358185-6a6ba616-b051-4b09-be0e-76f35495108e.png)

#### 示例代码

```java
public class Adapter2 {
    public static void main(String[] args) {
        Power power = new Power();
        PowerAdapter powerAdapter = new PowerAdapter(power);
        Integer integer = powerAdapter.output220V();
    }

    // 电压输出
    interface PowerTarget {
        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        Integer output220V();
    }

    @Setter
    @Getter
    static class PowerAdapter implements PowerTarget {
        private final Power power;

        public PowerAdapter(Power power) {
            this.power = power;
        }

        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        @Override
        public Integer output220V() {
            Integer output = power.getOutput();
            System.out.println("变压器交流" + output + "v转220v三相电变两项电。。。");

            double adapter = new Random().nextDouble(1.64, 1.72);
            Integer newOutput = (int) (output / adapter);
            System.out.println("变压器转换完成：电压输出为：" + newOutput);

            return newOutput;
        }

    }

    @Data
    static class Power {
        private Integer output = 380;

        public Integer output380V() {
            System.out.println("输出电压：" + output);
            return output;
        }
    }
}
```

#### 运行结果 ：

```java
变压器交流380v转220v三相电变两项电。。。
变压器转换完成：电压输出为：224
```

### 缺省适配器

![img](./images/1739543365541-f7f70bbc-7ddc-40e8-941d-966c53bbe290.png)

#### 示例代码

```java
public class Adapter3 {
    public static void main(String[] args) {
        Power power = new Power();
        PowerAdapter powerAdapter = new Power220VAdapter(power);
        Integer integer = powerAdapter.output220V();
    }

    // 电压输出
    interface PowerTarget {
        /**
         * 输出电压24V
         *
         * @return 输出电压
         */
        Integer output24V();

        /**
         * 输出电压110V
         *
         * @return 输出电压
         */
        Integer output110V();

        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        Integer output220V();
    }

    @Data
    static abstract class PowerAdapter implements PowerTarget {
        protected Power power;

        public PowerAdapter(Power power) {
            this.power = power;
        }

        /**
         * 输出电压24V
         *
         * @return 输出电压
         */
        @Override
        public Integer output24V() {
            return 0;
        }

        /**
         * 输出电压110V
         *
         * @return 输出电压
         */
        @Override
        public Integer output110V() {
            return 0;
        }

        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        @Override
        public Integer output220V() {
            return 0;
        }
    }

    // 缺省适配器转换器
    static class Power220VAdapter extends PowerAdapter {
        public Power220VAdapter(Power power) {
            super(power);
        }

        /**
         * 输出电压220V
         *
         * @return 输出电压
         */
        @Override
        public Integer output220V() {
            Integer output = power.getOutput();
            System.out.println("变压器开始转换：" + output + "v转220v三相电变两项电。。。");

            double adapter = new Random().nextDouble(1.64, 1.72);
            Integer newOutput = (int) (output / adapter);
            System.out.println("变压器转换完成：电压输出为：" + newOutput);

            return newOutput;
        }
    }

    @Data
    static class Power {
        private Integer output = 380;

        public Integer output380V() {
            System.out.println("输出电压：" + output);
            return output;
        }
    }
}
```

#### 运行结果：

```java
变压器开始转换：380v转220v三相电变两项电。。。
变压器转换完成：电压输出为：224
```

------

## 组合模式---结构型

组合模式（Composite Pattern）是一种结构型设计模式，用于将对象组合成树形结构以表示“部分-整体”层次结构。组合模式让客户端以统一的方式对待单个对象和对象组合。

![img](./images/1739543375741-2fa52f7c-d030-41d1-a67f-c71516617c90.png)

1. **Component（抽象组件）**：

- 定义了组合对象和叶子对象的共同接口。
- 在组合模式中，所有的“叶子”和“容器”类都实现此接口，因此客户端可以一致地对待这些对象。
- 例如，可以定义一个 `Operation` 方法，使得所有的组件（无论是叶子对象还是组合对象）都能执行该操作。

1. **Leaf（叶子节点）**：

- 叶子对象表示树的最末端元素，不再有子对象。
- 叶子对象继承自 `Component` 类，具体实现功能。
- 叶子对象不再包含子节点。

1. **Composite（组合节点）**：

- 组合对象也实现了 `Component` 接口，且包含多个子组件（即可以包含其他 `Leaf` 或 `Composite` 对象）。
- 组合节点负责将所有的叶子节点和子组合节点组织起来，实现“部分-整体”的结构。

### 简单示例

#### 示例代码

```java
public class Composite {
    public static void main(String[] args) {
        ConcreteCompany company = new ConcreteCompany("总公司");

        // 总公司的分公司
        ConcreteCompany subCompany1 = new ConcreteCompany("上海分公司");
        subCompany1.add(new HRDepartment("上海华东分公司"));
        subCompany1.add(new FinanceDepartment("上海华东分公司"));
        company.add(subCompany1);

        // 总公司的分公司
        ConcreteCompany subCompany2 = new ConcreteCompany("北京分公司");
        subCompany2.add(new HRDepartment("北京华东分公司"));
        subCompany2.add(new FinanceDepartment("北京华东分公司"));
        company.add(subCompany2);

        // 上海的南京分公司
        ConcreteCompany subCompany3 = new ConcreteCompany("南京分公司");
        subCompany3.add(new HRDepartment("南京华东分公司"));
        subCompany3.add(new FinanceDepartment("南京华东分公司"));
        subCompany1.add(subCompany3);

        System.out.println("---------------------显示组织图---------------------");
        company.display(1);

        System.out.println("---------------------显示职责---------------------");
        company.duty();
    }

    // Component 抽象子组件
    abstract static class Company {
        protected String name;

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

        /**
         * 添加节点
         *
         * @param company 子组件
         */
        public abstract void add(Company company);

        /**
         * 删除节点
         *
         * @param company 子组件
         */
        public abstract void remove(Company company);

        /**
         * 显示
         *
         * @param depth 深度
         */
        public abstract void display(int depth);

        /**
         * 职责
         */
        public abstract void duty();
    }

    // 容器对象
    static class ConcreteCompany extends Company {

        private final List<Company> companyList = new ArrayList<>();

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

        /**
         * 添加节点
         *
         * @param company 子组件
         */
        @Override
        public void add(Company company) {
            companyList.add(company);
        }

        /**
         * 删除节点
         *
         * @param company 子组件
         */
        @Override
        public void remove(Company company) {
            companyList.remove(company);
        }

        /**
         * 显示
         *
         * @param depth 深度
         */
        @Override
        public void display(int depth) {
            for (int i = 0; i < depth; i++) System.out.print("-");

            System.out.println(name);

            for (Company company : companyList) {
                company.display(depth + 1);
            }
        }

        /**
         * 职责
         */
        @Override
        public void duty() {
            for (Company company : companyList) {
                company.duty();
            }
        }
    }

    // 人事部门
    static class HRDepartment extends Company {
        public HRDepartment(String name) {
            super(name);
        }

        /**
         * 添加节点
         *
         * @param company 子组件
         */
        @Override
        public void add(Company company) {
        }

        /**
         * 删除节点
         *
         * @param company 子组件
         */
        @Override
        public void remove(Company company) {
        }

        /**
         * 显示
         *
         * @param depth 深度
         */
        @Override
        public void display(int depth) {
            for (int i = 0; i < depth; i++) System.out.print("-");
            System.out.println(name);
        }

        /**
         * 职责
         */
        @Override
        public void duty() {
            System.out.println(name + "：员工招聘培训管理");
        }
    }

    // 财务部
    static class FinanceDepartment extends Company {
        public FinanceDepartment(String name) {
            super(name);
        }

        /**
         * 添加节点
         *
         * @param company 子组件
         */
        @Override
        public void add(Company company) {
        }

        /**
         * 删除节点
         *
         * @param company 子组件
         */
        @Override
        public void remove(Company company) {
        }

        /**
         * 显示
         *
         * @param depth 深度
         */
        @Override
        public void display(int depth) {
            for (int i = 0; i < depth; i++) System.out.print("-");
            System.out.println(name);
        }

        /**
         * 职责
         */
        @Override
        public void duty() {
            System.out.println(name + "：公司财务收支管理");
        }
    }
}
```

#### 运行结果：

```java
---------------------显示组织图---------------------
-总公司
--上海分公司
---上海华东分公司
---上海华东分公司
---南京分公司
----南京华东分公司
----南京华东分公司
--北京分公司
---北京华东分公司
---北京华东分公司
---------------------显示职责---------------------
上海华东分公司：员工招聘培训管理
上海华东分公司：公司财务收支管理
南京华东分公司：员工招聘培训管理
南京华东分公司：公司财务收支管理
北京华东分公司：员工招聘培训管理
北京华东分公司：公司财务收支管理
```

------

## 享元模式---结构型

享元模式（Flyweight Pattern）是一种结构型设计模式，它的主要目的是通过共享对象来减少内存使用和提高性能。在享元模式中，系统中可能会有很多重复的对象，而享元模式通过将这些对象分为“共享部分”和“非共享部分”，只在共享部分创建单一实例，来优化内存使用。

![img](./images/1739543390275-1c1add39-94c0-4175-9813-e03d66c7c14b.png)

**需要角色**

**Flyweight（享元类）**：负责实现共享的对象部分，通常是不可变的状态。它是享元模式的核心，通过共享相同的状态，减少内存消耗。

**ConcreteFlyweight（具体享元类）**：是Flyweight的具体实现，负责实现具体的共享对象。具体享元类一般会包含一个外部状态，它并不存储该状态，而是通过外部传入的方式进行变化。

**FlyweightFactory（享元工厂类）**：是一个工厂，负责管理共享的享元对象。在客户端请求享元对象时，它会从池中查找是否已有实例，如果有则返回，若没有则创建新的享元对象并将其返回。

**Client（客户端）**：负责根据外部状态请求享元对象。客户端会传递外部状态（不共享的部分）给享元对象，而享元对象则只关注内部共享部分。

### 简单示例

#### 示例代码

```java
public class FlyWeight {
    public static void main(String[] args) {
        // 第一次获取对象会进行资源创建
        GirlFriend girlFriend1 = GirlFriendFactory.getGirlFriend("第一个女朋友");
        GirlFriend girlFriend2 = GirlFriendFactory.getGirlFriend("第二个女朋友");

        // 第二次获取对象直接从容器中获取
        GirlFriend girlFriend11 = GirlFriendFactory.getGirlFriend("第一个女朋友");
        GirlFriend girlFriend22 = GirlFriendFactory.getGirlFriend("第二个女朋友");

        System.out.println(girlFriend1 == girlFriend11);// true
        System.out.println(girlFriend2 == girlFriend22);// true
    }

    @Data
    static class GirlFriend {
        private String name;
        private Integer age;
    }

    static class GirlFriendFactory {
        private static final Map<String, GirlFriend> map = new HashMap<>();

        public static GirlFriend getGirlFriend(String name) {
            GirlFriend girlFriend = map.get(name);
            if (girlFriend == null) {
                girlFriend = new GirlFriend();
                girlFriend.name = name;
                map.put(name, girlFriend);
            }
            return girlFriend;
        }
    }
}
```

#### 运行结果：

```java
true
true
```

## 桥接模式---结构型

桥接模式通过“桥接”抽象和实现，使得两者可以独立地变化。它通常应用于那些有多个维度可扩展的系统中，这样可以避免类爆炸，减少子类的数量，提升代码的可维护性。

![img](./images/1739543396523-1491fbd4-ea92-4d2a-98e5-417feb76ec13.png)

**需要角色**

**Abstraction（抽象化角色）**：

- 定义了抽象部分的接口，并且保持一个指向实现部分的引用。

**RefinedAbstraction（扩充抽象化角色）**：

- 继承自 Abstraction，通常会扩展其接口。

**Implementor（实现者角色）**：

- 定义了实现类的接口，这个接口不会太复杂，可以和抽象角色分离。

**ConcreteImplementor（具体实现者角色）**：

- 实现了 Implementor 接口，定义了具体的实现方式。

### 简单示例

#### 示例代码

```java
public class Bridge {
    public static void main(String[] args) {
        // 使用不同的绘制方式
        Shape circle1 = new Circle(5, 10, 2, new DrawingAPI1());  // 使用屏幕绘制
        Shape circle2 = new Circle(10, 20, 3, new DrawingAPI2()); // 使用打印机绘制

        circle1.draw();
        circle2.draw();

        // 调整圆形大小
        circle1.resize(1.5);
        circle2.resize(0.5);

        circle1.draw();
        circle2.draw();
    }

    // Implementor: 定义绘制图形的接口
    interface DrawingAPI {
        void drawCircle(double x, double y, double radius);
    }

    // ConcreteImplementor: 屏幕绘制实现
    static class DrawingAPI1 implements DrawingAPI {
        @Override
        public void drawCircle(double x, double y, double radius) {
            System.out.println("Drawing Circle on Screen: (" + x + ", " + y + ") with radius " + radius);
        }
    }

    // ConcreteImplementor: 打印机绘制实现
    static class DrawingAPI2 implements DrawingAPI {
        @Override
        public void drawCircle(double x, double y, double radius) {
            System.out.println("Drawing Circle on Printer: (" + x + ", " + y + ") with radius " + radius);
        }
    }

    // Abstraction: 定义图形接口
    static abstract class Shape {
        protected DrawingAPI drawingAPI;

        protected Shape(DrawingAPI drawingAPI) {
            this.drawingAPI = drawingAPI;
        }

        public abstract void draw();

        public abstract void resize(double factor);
    }

    // RefinedAbstraction: 圆形
    static class Circle extends Shape {
        private final double x;
        private final double y;
        private double radius;

        public Circle(double x, double y, double radius, DrawingAPI drawingAPI) {
            super(drawingAPI);
            this.x = x;
            this.y = y;
            this.radius = radius;
        }

        @Override
        public void draw() {
            drawingAPI.drawCircle(x, y, radius);
        }

        @Override
        public void resize(double factor) {
            radius *= factor;
        }
    }
}
```

#### 运行结果：

```java
Drawing Circle on Screen: (5.0, 10.0) with radius 2.0
Drawing Circle on Printer: (10.0, 20.0) with radius 3.0
Drawing Circle on Screen: (5.0, 10.0) with radius 3.0
Drawing Circle on Printer: (10.0, 20.0) with radius 1.5
```

## 命令模式---行为型

**Command**：定义执行请求的接口（或抽象类）。

**ConcreteCommand**：实现命令接口并具体化执行请求的过程，通常还会持有接收者对象。

**Receiver**：具体的对象，完成实际的操作任务。

**Invoker**：调用命令的对象，触发命令的执行。

**Client**：客户端，负责创建并配置命令对象，将命令与接收者绑定，并传递给调用者执行。

### 简单示例

![img](./images/1739543409668-f29e12c4-fc44-48ec-b6d1-f4cfabad64dc.png)

#### 示例代码

```java
public class CommandDemo {
    public static void main(String[] args) {
        Receiver receiver = new Receiver();

        ConcreteCommand concreteCommand = new ConcreteCommand(receiver);

        Invoker invoker = new Invoker();
        invoker.setCommand(concreteCommand);
        invoker.invoke();
    }

    // 命令接口
    interface Command {

        /**
         * 执行方法
         */
        void execute();
    }

    //  接受者
    static class Receiver {
        public void action() {
            System.out.println("接受者 执行。。。");
        }
    }

    // 具体的执行命令
    static class ConcreteCommand implements Command {

        private final Receiver receiver;

        public ConcreteCommand(Receiver receiver) {
            this.receiver = receiver;
        }

        /**
         * 执行方法
         */
        @Override
        public void execute() {
            receiver.action();
        }
    }

    @Setter
    static class Invoker {
        private Command command;

        public void invoke() {
            command.execute();
        }
    }
}
```

#### 执行结果：

```java
接受者 执行。。。
```

### 示例-烧烤店

![img](./images/1739543425821-7c0a813b-150f-4cdf-9a5f-28f920926f7a.png)

#### 示例代码

```java
public class BakeDemo {

    // 充当客户端
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        Barbecue barbecue = new Barbecue();

        waiter.addCommand(new BakeChickenWing(barbecue));
        waiter.addCommand(new BakeMutton(barbecue));

        waiter.notifyCommand();
    }

    // 接受者-厨师
    static class Barbecue {

        /**
         * 烤串
         */
        public void bakeMutton() {
            System.out.println("开始烤串。。。");
        }

        /**
         * 烤鸡翅
         */
        public void bakeChickenWing() {
            System.out.println("开始烤鸡翅。。。");
        }
    }

    // 请求者-invoker-服务员
    public static class Waiter {
        private final List<Command> commandList = new ArrayList<>();

        public void addCommand(Command command) {
            commandList.add(command);
        }

        /**
         * 通知厨师开始制作
         */
        public void notifyCommand() {
            for (Command command : commandList) {
                command.execute();
            }
        }
    }

    public static abstract class Command {
        protected Barbecue barbecue;

        public Command(Barbecue barbecue) {
            this.barbecue = barbecue;
        }

        /**
         * 执行方法
         */
        public abstract void execute();
    }

    // 命令-烤鸡翅
    public static class BakeChickenWing extends Command {

        public BakeChickenWing(Barbecue barbecue) {
            super(barbecue);
        }

        /**
         * 执行方法
         */
        @Override
        public void execute() {
            barbecue.bakeChickenWing();
        }
    }

    // 命令-烤串
    public static class BakeMutton extends Command {

        public BakeMutton(Barbecue barbecue) {
            super(barbecue);
        }

        /**
         * 执行方法
         */
        @Override
        public void execute() {
            barbecue.bakeMutton();
        }
    }
}
```

#### 执行结果：

```java
开始烤鸡翅。。。
开始烤串。。。
```

------

## 状态模式---行为型

![img](./images/1739543435321-8824a5d5-20be-4025-a0e8-6440d02eab5a.png)

需要角色：状态对象（Context）、状态接口（State）、具体状态实现（Concrete State）

### 简单示例

#### 示例代码

**上下文对象**

```java
@Getter
public class Lift {
    // 开门状态
    public static LiftState OPEN_STATE = new OpeningLiftState();
    // 关门状态
    public static LiftState CLOSE_STATE = new ClosingLiftState();
    // 运行状态
    public static LiftState RUNNING_STATE = new RunningLiftState();
    // 停止状态
    public static LiftState STOPPING_STATE = new StoppingLiftState();

    // 当前电梯状态
    private LiftState currentLiftState;

    public void setCurrentLiftState(LiftState currentState) {
        this.currentLiftState = currentState;
        // 执行开门动作
        this.currentLiftState.lift = this;
    }

    public void open() {
        currentLiftState.open();
    }

    public void close() {
        currentLiftState.close();
    }

    public void run() {
        currentLiftState.run();
    }

    public void stop() {
        currentLiftState.stop();
    }
}
```

**抽象状态接口**

```java
@Setter
abstract class LiftState {
    protected Lift lift;

    /**
     * 开门动作
     */
    public abstract void open();

    /**
     * 关门动作
     */
    public abstract void close();

    /**
     * 运行动作
     */
    public abstract void run();

    /**
     * 停止动作
     */
    public abstract void stop();
}
```

**开门状态---具体状态实现**

```java
public class OpeningLiftState extends LiftState {
    /**
     * 开门动作
     */
    @Override
    public void open() {
        System.out.println("电梯门慢慢打开。。。");
    }

    /**
     * 关门动作
     */
    @Override
    public void close() {
        super.lift.setCurrentLiftState(Lift.CLOSE_STATE);
        super.lift.getCurrentLiftState().close();
    }

    /**
     * 运行动作
     */
    @Override
    public void run() {

    }

    /**
     * 停止动作
     */
    @Override
    public void stop() {

    }
}
```

**关门状态---具体状态实现**

```java
public class ClosingLiftState extends LiftState {
    /**
     * 开门动作
     */
    @Override
    public void open() {
        super.lift.setCurrentLiftState(Lift.OPEN_STATE);
        super.lift.getCurrentLiftState().open();
    }

    /**
     * 关门动作
     */
    @Override
    public void close() {
        System.out.println("电梯关门。。。");
    }

    /**
     * 运行动作
     */
    @Override
    public void run() {
        super.lift.setCurrentLiftState(Lift.RUNNING_STATE);
        super.lift.getCurrentLiftState().run();
    }

    /**
     * 停止动作
     */
    @Override
    public void stop() {
        super.lift.setCurrentLiftState(Lift.STOPPING_STATE);
        super.lift.getCurrentLiftState().stop();
    }
}
```

**运行状态---具体状态实现**

```java
public class RunningLiftState extends LiftState {
    /**
     * 开门动作
     */
    @Override
    public void open() {

    }

    /**
     * 关门动作
     */
    @Override
    public void close() {

    }

    /**
     * 运行动作
     */
    @Override
    public void run() {
        System.out.println("电梯正在运行。。。");
    }

    /**
     * 停止动作
     */
    @Override
    public void stop() {
        super.lift.setCurrentLiftState(Lift.STOPPING_STATE);
        super.lift.getCurrentLiftState().stop();
    }
}
```

**停止状态---具体状态实现**

```java
public class StoppingLiftState extends LiftState {
    /**
     * 开门动作
     */
    @Override
    public void open() {
        super.lift.setCurrentLiftState(Lift.OPEN_STATE);
        super.lift.getCurrentLiftState().open();
    }

    /**
     * 关门动作
     */
    @Override
    public void close() {

    }

    /**
     * 运行动作
     */
    @Override
    public void run() {
        super.lift.setCurrentLiftState(Lift.RUNNING_STATE);
        super.lift.getCurrentLiftState().run();
    }

    /**
     * 停止动作
     */
    @Override
    public void stop() {
        System.out.println("电梯停止。。。");
    }
}
```

#### 运行结果

**当运行时**

```java
public class Client {
    public static void main(String[] args) {
        Lift lift = new Lift();
        lift.setCurrentLiftState(Lift.RUNNING_STATE);
        lift.open();
        lift.run();
        lift.close();
        lift.stop();
    }
}
```

**运行结果**

```java
电梯正在运行。。。
电梯停止。。。
```

## 备忘录模式---行为型

**定义**：在不破坏封闭的前提下，捕获一个对象内部状态，并在该对象之外保存这个状态，这样以后就将该对象恢复到原先保存的状态。

需要角色：Originator（发起人）、Memento（备忘录）、Caretaker（管理者）

备忘录可以实现功能：撤销、重做、历史记录、快照。

### 简单示例

#### 示例代码

```java
public class Memo {
    public static void main(String[] args) {
        // 定义记事本
        NoteEditText noteEditText = new NoteEditText();

        // 负责管理记事本
        NoteCaretaker noteCaretaker = new NoteCaretaker();

        // 写入记录
        noteEditText.content = "创建第一条记录。。。";
        noteCaretaker.saveMemo(noteEditText.createMemo());

        // 再次写入
        noteEditText.content = "第三条记录。。。";
        noteCaretaker.saveMemo(noteEditText.createMemo());

        // 写错撤销下
        noteEditText.restoreMemo(noteCaretaker.getPrevMemo());
    }

    // 备忘录角色-备忘录
    @Getter
    static class Memento {
        private final String content;

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

    // 存储备忘录--管理者
    static class NoteCaretaker {
        private final List<Memento> mementoList = new ArrayList<>();

        // 存档位置
        private int index = 0;

        /**
         * 添加内容到备忘录中
         *
         * @param memento 备忘录
         */
        public void saveMemo(Memento memento) {
            mementoList.add(memento);
            index = mementoList.size() - 1;
            for (Memento memento1 : mementoList) {
                System.out.print(memento1.content + "  ");
            }
            System.out.println();
        }

        /**
         * 获取下一个
         *
         * @return 备忘录
         */
        public Memento getNextMemo() {
            index = index > (mementoList.size() - 1) ? index : mementoList.size() - 1;
            return mementoList.get(index);
        }

        /**
         * 获取上一个
         *
         * @return 备忘录
         */
        public Memento getPrevMemo() {
            index = index > 0 ? (index - 1) : 0;
            return mementoList.get(index);
        }
    }

    // 负责创建备忘录-发起人
    @Data
    static class NoteEditText {
        private String content;

        public Memento createMemo() {
            return new Memento(content);
        }

        public void restoreMemo(Memento memento) {
            this.content = memento.content;
            System.out.println("撤销记录：" + content);
        }
    }
}
```

#### 运行结果：

```java
创建第一条记录。。。  
创建第一条记录。。。  第三条记录。。。  
撤销记录：创建第一条记录。。。
```

## 中介者模式---行为型

![img](./images/1739543453266-941fb52f-e487-42e4-9168-c2478aa77628.png)

需要角色：抽象中介者、具体中介者、抽象同事类、具体同事类

### 简单示例

#### 代码示例

```java
public class Behavior {
    public static void main(String[] args) {
        // 创建邮局
        PostOfficeImpl postOffice = new PostOfficeImpl();

        // 创建收信人和接收人
        Me me = new Me(postOffice, "在地球南边");
        You you = new You(postOffice, "在地球北边");

        // 到邮局建立联系
        postOffice.addPeople(me);
        postOffice.addPeople(you);

        // 我：
        me.sendLetter("我的消息", "You");
        System.out.println("---------------分隔线---------------");

        // 你：
        you.sendLetter("你的回信", "You");
        System.out.println("---------------分隔线---------------");

        // 我：
        me.sendLetter("哈哈哈哈哈哈哈哈哈", "You");
    }

    // 抽象中介者
    interface PostOffice {

        /**
         * 送信
         */
        void deliverLetter(String letter, String receiver);

        /**
         * 添加人
         */
        void addPeople(People people);
    }

    @Data
    static class PostOfficeImpl implements PostOffice {
        private final Map<String, People> peopleMap = new HashMap<>();

        /**
         * 送信
         */
        @Override
        public void deliverLetter(String letter, String receiver) {
            System.out.println("=>收信：邮局收到要寄的信");

            People people = peopleMap.get(receiver);

            System.out.println("=>送信：拿出地址查询收件人地址是：" + people.getAddress() + "，送信");
            System.out.println("=>收信人看信：");

            people.receiveLetter(letter);
        }

        /**
         * 添加人
         */
        @Override
        public void addPeople(People people) {
            peopleMap.put(people.getClass().getSimpleName(), people);
        }
    }


    @Getter
    static class People {
        private final String address;
        protected PostOffice postOffice;

        public People(PostOffice postOffice, String address) {
            this.postOffice = postOffice;
            this.address = address;
        }

        /**
         * 收到信
         *
         * @param letter 信的内容
         */
        public void receiveLetter(String letter) {
            System.out.println(letter);
        }

        /**
         * 发送信
         *
         * @param letter   信内容
         * @param receiver 收件人
         */
        public void sendLetter(String letter, String receiver) {
            postOffice.deliverLetter(letter, receiver);
        }
    }

    static class Me extends People {
        public Me(PostOffice postOffice, String address) {
            super(postOffice, address);
        }
    }

    static class You extends People {
        public You(PostOffice postOffice, String address) {
            super(postOffice, address);
        }
    }
}
```

#### 运行结果：

```java
=>收信：邮局收到要寄的信
=>送信：拿出地址查询收件人地址是：在地球北边，送信
=>收信人看信：
我的消息
---------------分隔线---------------
=>收信：邮局收到要寄的信
=>送信：拿出地址查询收件人地址是：在地球北边，送信
=>收信人看信：
你的回信
---------------分隔线---------------
=>收信：邮局收到要寄的信
=>送信：拿出地址查询收件人地址是：在地球北边，送信
=>收信人看信：
哈哈哈哈哈哈哈哈哈
```

## 迭代器模式---行为型

**定义：**提供一种方法顺序访问一个聚合对象中的哥哥元素，而不是暴露其内部的表示。

![img](./images/1739543464309-ee4dde49-316b-4ee7-b0b3-499a1dabb4d2.png)

需要角色：抽象迭代器、具体迭代器、抽象聚合类、具体聚合类。

### 简单示例

#### 示例代码

```java
public class Iterator {

    public static void main(String[] args) {
        ListContainer listContainer = new ListContainer();
        listContainer.add("序号1");
        listContainer.add("序号2");
        listContainer.add("序号3");
        listContainer.add("序号4");

        MyIterator iterator = listContainer.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    // 迭代器接口
    interface MyIterator {

        boolean hasNext();

        Object next();
    }

    // 定义容器
    interface MyContainer {
        void add(Object o);

        void remove(Object o);

        MyIterator iterator();
    }

    // 列表操作容器
    static class ListContainer implements MyContainer {
        private final List<Object> list = new ArrayList<>();

        @Override
        public void add(Object o) {
            list.add(o);
        }

        @Override
        public void remove(Object o) {
            list.remove(o);
        }

        @Override
        public MyIterator iterator() {
            return new MyIteratorImpl();
        }

        class MyIteratorImpl implements MyIterator {

            private int index = 0;

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

            @Override
            public Object next() {
                Object object = list.get(index);
                index++;
                return object;
            }
        }
    }
}
```

#### 运行结果：

```java
序号1
序号2
序号3
序号4
```

## 访问者模式---行为型

访问者模式（Visitor Pattern）是一种行为设计模式，它允许你在不修改元素类的前提下，定义新的操作。通过使用访问者模式，可以将操作和元素的结构分离，从而让你在不修改元素类的情况下，向其中添加新的操作。

![img](./images/1739543488558-0c803560-cecb-43d6-99af-5892bb83bbe0.png)

**需要角色**

**Element（元素）**：所有的元素类都需要实现此接口，它定义了`accept()`方法来接受访问者的访问。

**ConcreteElement（具体元素）**：这是实现Element接口的类，代表具体的对象，可以是任何你希望执行操作的对象。

**Visitor（访问者）**：这个接口定义了对所有元素类的访问方法。

**ConcreteVisitor（具体访问者）**：这是实现Visitor接口的类，具体执行对元素的操作。

**Object Structure（对象结构）**：一个包含所有元素对象的容器。它遍历所有元素对象并调用它们的`accept()`方法，传入访问者进行操作。

### 简单示例

#### 代码示例

```java
public class VisitorDemo1 {
    public static void main(String[] args) {
        BusinessReport report = new BusinessReport();
        System.out.println("-------------------CEO-------------------");
        report.showReport(new CEOVisitor());

        System.out.println("-------------------CTO-------------------");
        report.showReport(new CTOVisitor());
    }

    // 访问者
    interface Visitor {
        /**
         * 访问者-工程师
         */
        void visit(Engineer engineer);

        /**
         * 访问者-经理
         */
        void visit(Manger manger);
    }

    // 具体访问者-CEO
    static class CEOVisitor implements Visitor {

        /**
         * 访问者-工程师
         *
         * @param engineer 工程师
         */
        @Override
        public void visit(Engineer engineer) {
            System.out.println("工程师：" + engineer.name + "，KPI：" + engineer.kpi);
        }

        /**
         * 访问者-经理
         *
         * @param manger 经理
         */
        @Override
        public void visit(Manger manger) {
            System.out.println("经理：" + manger.name + "，KPI：" + manger.kpi);
        }
    }

    // 具体访问者-CTO
    static class CTOVisitor implements Visitor {

        /**
         * 访问者-工程师
         *
         * @param engineer 工程师
         */
        @Override
        public void visit(Engineer engineer) {
            System.out.println("工程师：" + engineer.name + "，代码行数：" + engineer.getCodeLines());
        }

        /**
         * 访问者-经理
         *
         * @param manger 经理
         */
        @Override
        public void visit(Manger manger) {
            System.out.println("经理：" + manger.name + "，产品数：" + manger.getProducts());
        }
    }

    // 员工抽象
    static abstract class Employee {
        public String name;
        public int kpi;

        public Employee(String name) {
            this.name = name;
            this.kpi = new Random().nextInt(10);
        }

        // 接受访问者访问
        public abstract void accept(Visitor visitor);
    }

    // 员工具体---工程师
    static class Engineer extends Employee {

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

        /**
         * @param visitor 访问者
         */
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }

        public int getCodeLines() {
            return new Random().nextInt(10000);
        }
    }

    // 员工具体---经理
    static class Manger extends Employee {

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

        /**
         * @param visitor 访问者
         */
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }

        public int getProducts() {
            return new Random().nextInt(10);
        }
    }

    // 员工报表类
    static class BusinessReport {
        private final List<Employee> employeeList = new ArrayList<>();

        public BusinessReport() {
            employeeList.add(new Manger("经理-A"));
            employeeList.add(new Manger("经理-B"));
            employeeList.add(new Manger("经理-C"));
            employeeList.add(new Manger("经理-D"));
            employeeList.add(new Manger("经理-E"));
        }

        public void showReport(Visitor visitor) {
            for (Employee employee : employeeList) {
                employee.accept(visitor);
            }
        }
    }
}
```

#### 运行结果：

```java
-------------------CEO-------------------
经理：经理-A，KPI：9
经理：经理-B，KPI：6
经理：经理-C，KPI：7
经理：经理-D，KPI：6
经理：经理-E，KPI：9
-------------------CTO-------------------
经理：经理-A，产品数：7
经理：经理-B，产品数：4
经理：经理-C，产品数：9
经理：经理-D，产品数：9
经理：经理-E，产品数：2
```

## 解释器模式---行为型

## 责任链模式---行为型

主要有两个角色：抽象处理者（Handler）、具体处理者（Concrete Handler）

![img](./images/1739543503022-bd791e19-1c1a-4f55-8ce0-b30c749e6502.png)

### 简单示例

#### 代码示例

```java
public class Chain {

    // 过滤垃圾请求，为了演示需要清除【垃圾，辣鸡，腊鸡】这些词
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        // 设置责任链
        handlerA.setNextHandler(handlerB);
        handlerB.setNextHandler(handlerC);

        // 发起请求
        handlerA.handleRequest("过滤垃圾请求，为了演示需要清除【垃圾，辣鸡，腊鸡】这些词");
    }

    // ConcreteHandler类
    static class ConcreteHandlerA extends Handler {
        @Override
        public void handleRequest(String request) {
            // 处理"垃圾"
            String updatedRequest = request.replaceAll("垃圾", "");
            System.out.println("Handler A处理后: " + updatedRequest);

            if (nextHandler != null) {
                nextHandler.handleRequest(updatedRequest);  // 传递修改后的请求
            }
        }
    }

    static class ConcreteHandlerB extends Handler {
        @Override
        public void handleRequest(String request) {
            // 处理"辣鸡"
            String updatedRequest = request.replaceAll("辣鸡", "");
            System.out.println("Handler B处理后: " + updatedRequest);

            if (nextHandler != null) {
                nextHandler.handleRequest(updatedRequest);  // 传递修改后的请求
            }
        }
    }

    static class ConcreteHandlerC extends Handler {
        @Override
        public void handleRequest(String request) {
            // 处理"腊鸡"
            String updatedRequest = request.replaceAll("腊鸡", "");
            System.out.println("Handler C处理后: " + updatedRequest);

            if (nextHandler != null) {
                nextHandler.handleRequest(updatedRequest);  // 传递修改后的请求
            }
        }
    }

    // Handler类
    @Setter
    abstract static class Handler {
        protected Handler nextHandler;

        public abstract void handleRequest(String request);
    }
}
```

#### 运行结果：

```java
Handler A处理后: 过滤请求，为了演示需要清除【，辣鸡，腊鸡】这些词
Handler B处理后: 过滤请求，为了演示需要清除【，，腊鸡】这些词
Handler C处理后: 过滤请求，为了演示需要清除【，，】这些词
```