# 设计模式

设计模式是对许多业务和算法的抽象，因此学习起来具有一定的难度。短时间内掌握是不可能的，需要通过不断的实践和理解来积累经验。对于已经在职场上工作，但后期才开始学习设计模式的人来说，可能会面临更多的挑战。

在学习设计模式时，很多概念趋于理论化，且种类繁多（设计模式总共有23种），如果没有进行系统的梳理，可能很难直接应用到实际场景中。

设计模式中的抽象类通常是接口或抽象类，这些类的实现会根据具体的业务需求进行调整，因而不一定是唯一的实现方式。

在我学习过程中，我试图将所学的内容总结下来，但由于篇幅有限，无法一一列举所有场景，只能举出一些常见的例子。

---

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

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

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

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

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

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

### 工厂模式的类型

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. **难以理解和维护**：对于一些简单的应用程序，使用工厂模式可能会使得设计过于复杂，反而增加了理解和维护的难度。

---

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

### 懒汉模式

#### 双重检查锁定（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;
    }
}
```

#### 适用场景

- 如果单例对象比较重，且只在程序中某些特定情况下才使用，懒汉模式可以带来性能优势。
- 在低并发环境或单线程环境下，懒汉模式使用较为简单，不会有多线程安全问题。
- 对于高并发且需要频繁访问单例的场景，推荐使用**静态内部类**或**饿汉模式**来避免懒汉模式可能带来的性能问题。

- **优点**：
  1. 延迟加载，节省资源。
  2. 内存优化，只有在需要时才实例化。
  3. 减少不必要的初始化开销。
- **缺点**：
  1. 传统懒汉模式线程不安全（多个线程可能会创建多个实例）。
  2. 使用同步机制会有性能开销，特别是在多线程环境下。
  3. 代码复杂性较高，容易引入错误。
  4. 不适合高并发场景，特别是频繁访问时会影响性能。

### 饿汉模式

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

```java
public class Singleton {

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

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

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

#### 适用场景

- **简单应用**：适合没有延迟初始化需求的小型应用，或者单例对象的创建非常轻量，不会影响系统性能的场景。
- **实例化不耗费太多资源**：如果单例对象的初始化过程非常轻量级且无须延迟初始化，可以使用饿汉模式。
- **类加载顺序固定**：如果不在乎单例对象在启动时是否初始化，且单例对象的初始化过程没有严重性能损失，可以选择饿汉模式。

- **优点**：简单、线程安全、性能高（没有锁机制）、实现方便。
- **缺点**：不支持延迟加载、可能会浪费资源（如果单例对象不常用时）。

饿汉模式是单例模式中最简单的实现方式，适用于大多数情况下单例对象的创建开销较小，且不需要延迟初始化的场景。如果单例对象的创建非常轻量且不依赖于后期加载时的资源，饿汉模式是一个不错的选择。

### 枚举类型实现

**枚举类型实现单例模式**（Enum Singleton）是实现单例模式的另一种方式，优点是更加简洁、可靠，并且避免了许多常见的单例实现方式（如懒汉模式和饿汉模式）可能出现的问题。使用枚举类型的单例实现方式自
**Java 5** 引入以来，已经成为了最推荐的单例模式实现方式之一。

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

```java
public enum Singleton {

    // 唯一实例
    INSTANCE;

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

#### 使用示例

```java
public class Main {
    public static void main(String[] args) {
        // 获取单例对象
        Singleton singleton = Singleton.INSTANCE;

        // 调用单例方法
        singleton.someMethod();
    }
}
```

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

![image-20250202214232289](./images/设计模式-v2/image-20250202214232289.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
```

---

## 建造者模式

![image-20250201203116885](./images/设计模式-v2/image-20250201203116885.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)
```

---

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

一共有四个角色。

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

### 简单示例

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

![image-20250201185356903](./images/设计模式-v2/image-20250201185356903.png)

#### 代码实现

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
相机拍照。。。
美颜功能。。。
滤镜效果。。。
```

---

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

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

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

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

![image-20250203154216552](./images/设计模式-v2/image-20250203154216552.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
打开手机。。。
打开天气。。。
关闭天气。。。
关闭手机。。。
```

---

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

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

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

![](./images/设计模式-v2/v2-8efc399313ae3746932c63069aa103b0_1440w-1738507407103-4.avif)

### 类适配器

![image-20250202222740030](./images/设计模式-v2/image-20250202222740030.png)

#### 示例代码

```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
```

### 对象适配器 

![image-20250202223220831](./images/设计模式-v2/image-20250202223220831.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
```

### 缺省适配器

![image-20250202224211540](./images/设计模式-v2/image-20250202224211540.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
```

---

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

---

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

---

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

---

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

---

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

### 常见应用场景

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

### 策略模式基础介绍

策略模式涉及三个主要角色：  

1. **抽象策略（Strategy）**  
2. **具体策略（Concrete Strategy）**  
3. **上下文（Context）**

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

![策略模式结构图](./images/设计模式-v2/image-20250201164040235.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`。

![image-20250201173433406](./images/设计模式-v2/image-20250201173433406.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：🪓 🪓 🪓和🔪 🔪 🔪
```

---

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

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

![image-20250201175728138](./images/设计模式-v2/image-20250201175728138.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 接受到消息：需要和妹妹说点悄悄话，将女朋友移除了，这时女朋友听不见我们说话。。。
```

---

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

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

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

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

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

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

### 简单示例

![image-20250201205350467](./images/设计模式-v2/image-20250201205350467.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
接受者 执行。。。
```

### 示例-烧烤店

![image-20250201205232542](./images/设计模式-v2/image-20250201205232542.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
开始烤鸡翅。。。
开始烤串。。。
```

---

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

---

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

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

需要的角色：抽象类（Abstract Class）、具体类（Concrete Class）。

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

### 简单示例

#### 示例代码

#### 运行结果：

```java

```

---

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

---

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

---

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

---

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

---

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

---

## 责任链模式---行为型-未完成。。。

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

![image-20250202201204954](./images/设计模式-v2/image-20250202201204954.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处理后: 过滤请求，为了演示需要清除【，，】这些词
```

### 
