# 设计模式 设计模式是对许多业务和算法的抽象,因此学习起来具有一定的难度。短时间内掌握是不可能的,需要通过不断的实践和理解来积累经验。对于已经在职场上工作,但后期才开始学习设计模式的人来说,可能会面临更多的挑战。 在学习设计模式时,很多概念趋于理论化,且种类繁多(设计模式总共有23种),如果没有进行系统的梳理,可能很难直接应用到实际场景中。 设计模式中的抽象类通常是接口或抽象类,这些类的实现会根据具体的业务需求进行调整,因而不一定是唯一的实现方式。 在我学习过程中,我试图将所学的内容总结下来,但由于篇幅有限,无法一一列举所有场景,只能举出一些常见的例子。 --- ## 工厂模式---创建型 ### 工厂模式(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. **难以理解和维护**:对于一些简单的应用程序,使用工厂模式可能会使得设计过于复杂,反而增加了理解和维护的难度。 --- ## 单例模式---创建型 ### 懒汉模式 #### 双重检查锁定(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 ``` --- ## 组合模式---结构型 组合模式(Composite Pattern)是一种结构型设计模式,用于将对象组合成树形结构以表示“部分-整体”层次结构。组合模式让客户端以统一的方式对待单个对象和对象组合。 ![image-20250203210907388](./images/设计模式-v2/image-20250203210907388.png) 1. **Component(抽象组件)**: - 定义了组合对象和叶子对象的共同接口。 - 在组合模式中,所有的“叶子”和“容器”类都实现此接口,因此客户端可以一致地对待这些对象。 - 例如,可以定义一个 `Operation` 方法,使得所有的组件(无论是叶子对象还是组合对象)都能执行该操作。 2. **Leaf(叶子节点)**: - 叶子对象表示树的最末端元素,不再有子对象。 - 叶子对象继承自 `Component` 类,具体实现功能。 - 叶子对象不再包含子节点。 3. **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 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)是一种结构型设计模式,它的主要目的是通过共享对象来减少内存使用和提高性能。在享元模式中,系统中可能会有很多重复的对象,而享元模式通过将这些对象分为“共享部分”和“非共享部分”,只在共享部分创建单一实例,来优化内存使用。 ![image-20250204191157193](./images/设计模式-v2/image-20250204191157193.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 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 ``` ## 代理模式---结构型 ### 静态代理-1 ![image-20250204185312828](./images/设计模式-v2/image-20250204185312828.png) 如果是静态代理,做Java开发几乎都在用,就是抽象接口和实现,比如:`UserService`之后`UserServiceImpl`实现`UserService`,就是这个,之后使用`UserService`进行调用实现中的方法。 ### 静态代理-2 ![image-20250204185852710](./images/设计模式-v2/image-20250204185852710.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 保存用户 查找用户 ``` --- ## 桥接模式---结构型 桥接模式通过“桥接”抽象和实现,使得两者可以独立地变化。它通常应用于那些有多个维度可扩展的系统中,这样可以避免类爆炸,减少子类的数量,提升代码的可维护性。 ![image-20250205223403477](./images/设计模式-v2/image-20250205223403477.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 ``` --- ## 策略模式---行为型 ### 常见应用场景 策略模式广泛应用于支付、计算、文件压缩、登录等场景,尤其是在游戏中,如王者荣耀和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 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 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 开始烤鸡翅。。。 开始烤串。。。 ``` --- ## 状态模式---行为型 ![image-20250204181749629](./images/设计模式-v2/image-20250204181749629.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 电梯正在运行。。。 电梯停止。。。 ``` --- ## 模板方法模式---行为型 将定义好的按步骤执行的内容进行封装,模板方法是比较单间的设计模式,是代码复用的基本技术,在类库中尤其重要,遵循:“抽象类应当拥有尽可能多的可能性,应当拥有尽可能少的数据”。 ![image-20250203163253869](./images/设计模式-v2/image-20250203163253869.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亿元 ``` --- ## 备忘录模式---行为型 **定义**:在不破坏封闭的前提下,捕获一个对象内部状态,并在该对象之外保存这个状态,这样以后就将该对象恢复到原先保存的状态。 需要角色: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 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 创建第一条记录。。。 创建第一条记录。。。 第三条记录。。。 撤销记录:创建第一条记录。。。 ``` --- ## 中介者模式---行为型 ![image-20250204184241160](./images/设计模式-v2/image-20250204184241160.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 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 =>收信:邮局收到要寄的信 =>送信:拿出地址查询收件人地址是:在地球北边,送信 =>收信人看信: 我的消息 ---------------分隔线--------------- =>收信:邮局收到要寄的信 =>送信:拿出地址查询收件人地址是:在地球北边,送信 =>收信人看信: 你的回信 ---------------分隔线--------------- =>收信:邮局收到要寄的信 =>送信:拿出地址查询收件人地址是:在地球北边,送信 =>收信人看信: 哈哈哈哈哈哈哈哈哈 ``` ## 迭代器模式---行为型 **定义:**提供一种方法顺序访问一个聚合对象中的哥哥元素,而不是暴露其内部的表示。 ![image-20250203173419155](./images/设计模式-v2/image-20250203173419155.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 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)是一种行为设计模式,它允许你在不修改元素类的前提下,定义新的操作。通过使用访问者模式,可以将操作和元素的结构分离,从而让你在不修改元素类的情况下,向其中添加新的操作。 ![image-20250206163950552](./images/设计模式-v2/image-20250206163950552.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 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) ![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处理后: 过滤请求,为了演示需要清除【,,】这些词 ```