# DesignPattern **Repository Path**: fly-liuhao/design-pattern ## Basic Information - **Project Name**: DesignPattern - **Description**: Java 23种设计模式学习笔记 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-03-27 - **Last Updated**: 2025-02-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: DesignPattern, Java, 设计模式 ## README ## 23种设计模式 > 参考网站:[菜鸟教程](https://www.runoob.com/design-pattern/factory-pattern.html) > > CSDN参考笔记:[23种设计模式](https://blog.csdn.net/weixin_48052161/category_10336915.html) > > 知乎笔记:[23 种设计模式详解](https://zhuanlan.zhihu.com/p/575645658) > > 知乎笔记:[23种设计模式通俗理解](https://zhuanlan.zhihu.com/p/100746724) ### 简要介绍 > 根据**目的**划分为三种 > > - 创建型模式:用于描述“怎样创建对象”。 > > - 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构。 > > - 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。 | 分类 | 具体设计模式 | | ---------------------------- | ------------------------------------------------------------ | | 创建型模式Creational(5种) | 工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、单实例模式(Singleton)、构造器模式(Builder)、原型模式(Prototype) | | 结构型模式Structural(7种) | 适配器模式(Adapter)、桥模式(Bridge)、组合模式(Composite)、装饰者模式(Decorator)、外观模式(Facade)、享元模式(Flyweight)、代理模式(Proxy) | | 行为型模式Behavioral(11种) | 职责链模式(Chain of Responsibility)、命令模式(Command)、迭代器模式(Iterator)、解释器模式(Interpreter)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy)、模板方法模式(Template Method)、访问者模式(Visitor) | ### 一、单例模式(singleton) - 定义:确保一个类最多只有一个实例,并提供一个全局访问点 - 实现方式有两种:预加载和懒加载,推荐使用饿汉式、以及静态内部类方式,具体使用哪个看是不是需要延迟加载对象 - 应用:Spring中 #### 1.饿汉式 > 类加载到内存后,就实例化一个单例,JVM保证**线程安全**,简单使用推荐使用 > > 缺点:不管用到与否,类加载的时候就完成实例化,造成资源浪费 ```java public class HungrySingleton { // 此final可写可不写,策略问题,写上最好 private static final HungrySingleton INSTANCE = new HungrySingleton(); private HungrySingleton() { // 防止通过反射进行实例化(注意,此方式不严谨,反射可以修改单例对象引用) if (INSTANCE != null) { throw new IllegalStateException("单例对象已经初始化!"); } } public static HungrySingleton getInstance() { return INSTANCE; } } ``` #### 2.懒汉式 > 懒加载,通过synchronized解决线程安全问题,但也带来效率下降 ```java public class LazySingleton { private static LazySingleton instance; private LazySingleton() { // 防止通过反射进行实例化(注意,此方式不严谨,反射可以修改单例对象引用) if (instance != null) { throw new IllegalStateException("单例对象已经初始化!"); } } public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } } ``` #### 3.双重检验锁 > 懒加载,通过synchronized解决线程安全问题,但也带来效率下降(比方式2好一些) ```java public class DoubleCheckLockSingleton { // volatile可以在对象创建时防止指令重排,多线程访问时报错 private static volatile DoubleCheckLockSingleton instance; private DoubleCheckLockSingleton() { // 防止通过反射进行实例化(注意,此方式不严谨,反射可以修改单例对象引用) if (instance != null) { throw new IllegalStateException("单例对象已经初始化!"); } } public static DoubleCheckLockSingleton getInstance() { // 第一次判断:方式重复获取释放锁造成资源浪费 if (instance == null) { synchronized (DoubleCheckLockSingleton.class) { // 第二次判断:防止多线程调用是时重复创建对象 if (instance == null) { instance = new DoubleCheckLockSingleton(); } } } return instance; } } ``` #### 4.静态内部类 > 懒加载,且线程安全,JVM保证单例 ```java public class StaticInnerClassSingleton { private StaticInnerClassSingleton() { // 防止通过反射进行实例化(注意,此方式不严谨,反射可以修改单例对象引用) if (HelperHolder.INSTANCE != null) { throw new IllegalStateException("单例对象已经初始化!"); } } public static StaticInnerClassSingleton getInstance() { return HelperHolder.INSTANCE; } /** * 持有单例对象的静态内部类 */ private static class HelperHolder { // 此final可写可不写,策略问题,写上最好 private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton(); } } ``` #### 5.枚举 > 线程安全,可以防止反射、反序列化 ```java public enum EnumSingleton { INSTANCE; public static EnumSingleton getInstance() { return INSTANCE; } } ``` #### 6.Spring 注册式单例 ```java public class RegSingleton { // 单例注册容器 private static final Map singletonCache = new ConcurrentHashMap(); // 静态块,在类被加载时自动执行 static { RegSingleton rs = new RegSingleton(); singletonCache.put(rs.getClass().getName(), rs); } private RegSingleton() { } public static Object getInstance(String beanName) { if (beanName == null) { return null; } if (singletonCache.get(beanName) == null) { try { singletonCache.put(beanName, Class.forName(beanName).newInstance()); } catch (Exception ex) { ex.printStackTrace(); } } return singletonCache.get(beanName); } } ``` #### 补充:线程单例实现 ```java public class ThreadSingleton { // 初始化ThreadLocal方式一 private static final ThreadLocal threadLocal = ThreadLocal.withInitial(() -> new ThreadSingleton()); // 初始化ThreadLocal方式二 // private static final ThreadLocal threadLocal = new ThreadLocal() { // @Override // protected Singleton06 initialValue() { // return new Singleton06(); // } // }; private ThreadSingleton() { } public static ThreadSingleton getInstance() { return threadLocal.get(); } // 测试多线程生成对象 public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(() -> System.out.println(ThreadSingleton.getInstance())).start(); } } } ``` #### 破坏单例的方式 1. **反射** 应对策略:构造函数中判断对象是否为空,不为空抛出异常(反射可以修改实例对象引用地址,不完全可靠) 2. 序列化 应对策略:不实现Serializable接口,或添加readResolve()方法,反序列化ObjectInputStream的readOrdinaryObject)()方法有校验,有此方法直接调用此方法返回对象 3. clone 应对策略:不实现Coloneable接口,或重新clone方法,放回单例对象 #### 应用场景 1. Spring IOC 2. 一些业务工具类、工厂类 ### 二、策略模式(Strategy) #### 1. Comparable ```java public interface Comparable { int compareTo(T o); } public class Cat implements Comparable { int weight, height; public Cat(int weight, int height) { this.weight = weight; this.height = height; } public int compareTo(Cat c) { if (this.weight < c.weight) return -1; else if (this.weight > c.weight) return 1; else return 0; } @Override public String toString() { return "Cat{" + "weight=" + weight + ", height=" + height + '}'; } } public class Sorter { public void sort(T[] arr, Comparator comparator) { for(int i=0; i sorter = new Sorter<>(); sorter.sort(a, (o1, o2)->{ if(o1.weight < o2.weight) return -1; else if (o1.weight>o2.weight) return 1; else return 0; }); System.out.println(Arrays.toString(a)); } } ``` #### 2. Comparator > Comparator就是一个策略模式 ```java // 定义策略接口 @FunctionalInterface // 函数式接口声明 public interface Comparator { int compare(T o1, T o2); } // 具体策略实现一 public class CatHeightComparator implements Comparator { @Override public int compare(Cat o1, Cat o2) { if(o1.height > o2.height) return -1; else if (o1.height < o2.height) return 1; else return 0; } } // 具体策略实现二 public class CatWeightComparator implements Comparator { @Override public int compare(Cat o1, Cat o2) { if(o1.weight < o2.weight) return -1; else if (o1.weight > o2.weight) return 1; else return 0; } } // 工具类:方法入参为策略接口的实现 public class Sorter { public void sort(T[] arr, Comparator comparator) { for(int i=0; i sorter = new Sorter<>(); sorter.sort(a, (o1, o2)->{ if(o1.weight < o2.weight) return -1; else if (o1.weight>o2.weight) return 1; else return 0; }); System.out.println(Arrays.toString(a)); } } ``` ### 三、工厂模式 > 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 #### 1.简单工厂(SimpleFactory) > 一旦对象创建方式进行改变,所有创建对象的 ```java // 工厂类 public class SimpleFactory { //工厂方法.注意返回类型为抽象产品角色 public static Car driverCar(String s) { if (s.equalsIgnoreCase("Benz")) { return new Benz(); } else if (s.equalsIgnoreCase("Bmw")) { return new Bmw(); } return null; } } ``` #### 2.工厂方法模式(FactoryMethod) - 作用:工厂接口负责定义创建对象的公共接口,创建工厂负责具体的创建对象。对象的实例化操作延迟到具体的工厂中完成 - 优点:减少了耦合性,保持了封装性 - 缺点:每增加一个产品就要添加一个工厂类,增加系统的复杂度 - 适用场景: - 创建对象时需要使用大量的代码 - 无需客户端知道具体的对象创建的细节以及以来关系,只需要对应工厂知道即可 ```java // 工厂接口 public interface CarFactory { Car driverCar(); } // 工厂接口实现一 public class BenzFactory implements CarFactory{ @Override public Car driverCar() { return new Benz(); } } // 工厂接口实现二 public class BmwFactory implements CarFactory{ @Override public Car driverCar() { return new Bmw(); } } // 测试 public class Main { public static void main(String[] args) throws Exception { CarFactory factory = new BmwFactory(); Car car = factory.driverCar(); car.drive(); } } ``` #### 3.抽象工厂模式(AbstractFactory) - 作用 - 抽象工厂模式为创建一组对象提供了一种解决方案。 - 与工厂方法模式相比, 抽象工厂模式中的具体工厂不只是创建一种具体对象,它负责创建一组(族)具体对象。 - 应用场景: - 在 Spring 中,BeanFactory 是用于管理 Bean 的一个工厂,所有工厂都是 BeanFactory 的子类。这样我们可以通过 IOC 容器来管理访问 Bean,根据不同的策略调用 getBean() 方法,从而获得具体对象。BeanFactory 的子类主要有 ClassPathXmlApplicationContext、XmlWebApplicationContext、StaticWebApplicationContext、StaticApplicationContext。在 Spring 中,DefaultListableBeanFactory 实现了所有工厂的公共逻辑。 - 类和对象关系:抽象工厂接口 + 具体工厂类 + 抽象产品接口 + 具体产品类 ```java // 抽象工厂接口 public abstract class AbstractFactory { //制造汽车 abstract Car driverCar(); //制造飞机 abstract Plane driverPlane(); //制造坦克 abstract Tank driverTank(); } // 抽象工厂接口实现一 public class BenzFactory extends AbstractFactory { @Override public Car driverCar() { return new BenzCar(); } @Override public Plane driverPlane() { return new BenzPlane(); } @Override public Tank driverTank() { return new BenzTank(); } } // 抽象工厂接口实现二 public class BmwFactory extends AbstractFactory { @Override public Car driverCar() { return new BmwCar(); } @Override public Plane driverPlane() { return new BmwPlane(); } @Override public Tank driverTank() { return new BmwTank(); } } public class Main { public static void main(String[] args) throws Exception { AbstractFactory factory = new BmwFactory(); Car car = factory.driverCar(); Plane plane = factory.driverPlane(); Tank tank = factory.driverTank(); car.drive(); plane.drive(); tank.drive(); } } ``` #### 总结 | 模式 | 简单工厂 | 工厂方法 | 抽象工厂 | | -------- | ------------------------------ | -------------------- | -------------------- | | 特点 | 一个工厂创建所有类型产品 | 每个产品有对应的工厂 | 每个工厂创建多个产品 | | 应用场景 | 产品较少,解耦客户端和具体产品 | 产品线较多 | 创建一系列相关的产品 | ### 四、外观模式/门面模式(Faced) - 定义: - 隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口,这个接口可以用来访问相同子系统或者不同子系统之中的一群接口。 - 在外观模式中,我们创建一个外观类,该类包含了客户端需要访问的子系统的所有方法。客户端只需要与外观类交互,而不需要直接与子系统交互。这样,客户端就可以通过一个简单的接口来访问系统的功能,而无需了解系统的内部实现细节。 - 于中介区别:门面模式对外提供一个接口、中介模式对内提供一个接口 - 角色:门面角色、子系统角色、客户角色 - 优点 - 松散耦合:使得客户端和子系统之间解耦,让子系统内部的模块功能更容易扩展和维护; - 简单易用:客户端根本不需要知道子系统内部的实现,或者根本不需要知道子系统内部的构成,它只需要跟Facade类交互即可 - 更好的划分访问层次:有些方法是对系统外的,有些方法是系统内部相互交互的使用的。子系统把那些暴露给外部的功能集中到门面中,这样就可以实现客户端的使用,很好的隐藏了子系统内部的细节。 - Code > 在下面的示例代码中,我们创建了三个子系统类:CPU、Disk和Memory。然后,我们创建了一个外观类Computer,该类包含了子系统类的所有方法。最后,我们创建了一个客户端测试类MainTest,该类使用外观类来访问子系统的功能。 > > 当客户端调用外观类的方法时,外观类会将请求转发给子系统类。客户端不需要知道子系统类的实现细节,只需要知道如何使用外观类的方法即可。这样,外观模式可以帮助我们将复杂的系统分解为更小的模块,并提供一个简单的接口来访问这些模块。 ```java // 子系统类 public class CPU { public void start() { System.out.println("cpu is start..."); } public void shutDown() { System.out.println("CPU is shutDown..."); } } public class Disk { public void start() { System.out.println("Disk is start..."); } public void shutDown() { System.out.println("Disk is shutDown..."); } } public class Memory { public void start() { System.out.println("Memory is start..."); } public void shutDown() { System.out.println("Memory is shutDown..."); } } // 门面类Facade public class Computer { private CPU cpu; private Memory memory; private Disk disk; public Computer() { cpu = new CPU(); memory = new Memory(); disk = new Disk(); } public void start() { System.out.println("Computer start begin"); cpu.start(); disk.start(); memory.start(); System.out.println("Computer start end"); } public void shutDown() { System.out.println("Computer shutDown begin"); cpu.shutDown(); disk.shutDown(); memory.shutDown(); System.out.println("Computer shutDown end..."); } } // 测试类 public class MainTest { public static void main(String[] args) { Computer computer = new Computer(); computer.start(); System.out.println("================="); computer.shutDown(); } } ``` ### 五、调停者模式(Mediator) - 定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。 - 角色 - 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。 - 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。 - 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。 - 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。 - 优点: - 降低了对象之间的耦合性,使得对象易于独立地被复用。 - 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。 - 缺点:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。 - 应用:消息中间件 - Code ```// 抽象中介者 // 抽象中介者 public interface Mediator { void register(Colleague colleague); // 客户注册 void relay(String from, String to,String ad); // 转发 } // 具体中介者 public class ConcreteMediator implements Mediator { private List colleagues = new ArrayList(); @Override public void register(Colleague colleague) { if (!colleagues.contains(colleague)) { colleagues.add(colleague); colleague.setMedium(this); } } @Override public void relay(String from, String to, String ad) { for (Colleague cl : colleagues) { String name = cl.getName(); if (name.equals(to)) { cl.receive(from, ad); } } } } // 抽象同事类 public abstract class Colleague { protected Mediator mediator; protected String name; public Colleague(String name) { this.name = name; } public void setMedium(Mediator mediator) { this.mediator = mediator; } public String getName() { return name; } public abstract void Send(String to, String ad); public abstract void receive(String from, String ad); } // 具体同事类 public class Buyer extends Colleague { public Buyer(String name) { super(name); } @Override public void Send(String to, String ad) { mediator.relay(name, to, ad); } @Override public void receive(String from, String ad) { System.out.println(name + "接收到来自" + from + "的消息:" + ad); } } // 测试类 public class MainTest { public static void main(String[] args) { // 创建中介 ConcreteMediator mediator = new ConcreteMediator(); // 创建两个同事 ConcreteColleague zhangSan = new ConcreteColleague("张三"); ConcreteColleague liSi = new ConcreteColleague("李四"); // 中介关联具体的同事对象 mediator.register(zhangSan); mediator.register(liSi); // 发送消息 zhangSan.send("李四", "你好,我是张三"); } } ``` ### 六、装饰器模式(Decorator) - 定义:在不改变原有对象的情况下,动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。 - 角色: - *1.Component(被装饰对象的基类)*定义一个对象接口,可以给这些对象动态地添加职责。 - *2.ConcreteComponent(具体被装饰对象)*定义一个对象,可以给这个对象添加一些职责。 - *3.Decorator(装饰者抽象类)*维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。 - *4.ConcreteDecorator(具体装饰者)*具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。被装饰对象和修饰者继承自同一个超类 - 适用场景: - 在不影响其他对象的情况下,对单个对象进行动态且可重复的功能扩展。 - 当需要为一个对象添加一些特定于特定场景的功能时,可以使用装饰者模式代替子类化。 - 总结:装饰者和被装饰者之间必须是一样的类型,也就是要有共同的超类。在这里应用继承并不是实现方法的复制,而是实现类型的匹配。因为装饰者和被装饰者是同一个类型,因此装饰者可以取代被装饰者,这样就使被装饰者拥有了装饰者独有的行为。根据装饰者模式的理念,我们可以在任何时候,实现新的装饰者增加新的行为。如果是用继承,每当需要增加新的行为时,就要修改原程序了。 - Code ```java // 定义组件接口 interface Component { void operation(); } // 定义具体组件类 class ConcreteComponent implements Component { @Override public void operation() { System.out.println("执行具体组件的操作"); } } // 定义装饰器类 class Decorator implements Component { private Component component; public Decorator(Component component) { this.component = component; } @Override public void operation() { component.operation(); } } // 定义具体装饰器类A class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } @Override public void operation() { super.operation(); addedBehavior(); } private void addedBehavior() { System.out.println("为具体组件A增加额外的操作"); } } // 定义具体装饰器类B class ConcreteDecoratorB extends Decorator { public ConcreteDecoratorB(Component component) { super(component); } @Override public void operation() { super.operation(); addedBehavior(); } private void addedBehavior() { System.out.println("为具体组件B增加额外的操作"); } } // 测试类 public class MainTest { public static void main(String[] args) { // 创建未装饰前组件对象 Component component = new ConcreteComponent(); // 创建装饰对象A Component decoratorA = new ConcreteDecoratorA(component); decoratorA.operation(); // 执行装饰器A对象的装饰后的operation()方法 // 创建装饰对象B Component decoratorB = new ConcreteDecoratorB(decoratorA); decoratorB.operation(); // 执行装饰器B对象的装饰后的operation()方法 } } ``` ### 七、责任链模式(Chain Of Responsibility) - 定义:如果有多个对象有机会处理请求,责任链可使请求的发送者和接受者解耦,请求沿着责任链传递,直到有一个对象处理了它为止。 - 主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。 - 何时使用:在处理消息的时候以过滤很多道。 - 如何解决:拦截的类都实现统一接口。 - 关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。 - 角色 - 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。 - 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。 - 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。 - 应用场景 - 多条件流程判断:权限控制 - Java 过滤器的底层实现 Filter - Mybatis Interceptor底层实现 - Netty中责任链模式的使用:https://blog.csdn.net/qq_33373609/article/details/120525169 - 代码示例一 ```java // 抽象处理者 public abstract class AbstractHandler { public abstract boolean handler(); } // 具体处理者1 public class FirstPassHandler extends AbstractHandler{ @Override public boolean handler() { System.out.println("FirstPassHandler进行处理...."); return true; } } // 具体处理者2 public class SecondPassHandler extends AbstractHandler { @Override public boolean handler() { System.out.println("SecondPassHandler进行处理...."); return true; } } // 客户类 public class HandlerChain { private final List handlerList = new ArrayList<>(); public HandlerChain addHandler(AbstractHandler handler) { handlerList.add(handler); return this; } public boolean handle() { boolean resultFlag = true; for (AbstractHandler handler : handlerList) { if (!handler.handler()) { resultFlag = false; break; } } return resultFlag; } } // 测试类 public class MainTest { public static void main(String[] args) { HandlerChain handlerChain = new HandlerChain(); handlerChain.addHandler(new FirstPassHandler()).addHandler(new SecondPassHandler()); handlerChain.handle(); } } ``` - Code2 ```java // 抽象处理类 public abstract class AbstractHandler { protected AbstractHandler successor; public void setSuccessor(AbstractHandler successor) { this.successor = successor; } public abstract boolean handler(); } // 具体处理类1 public class FirstPassHandler extends AbstractHandler { @Override public boolean handler() { System.out.println("FirstPassHandler进行处理...."); if (successor != null) { return successor.handler(); } return true; } } // 具体处理类2 public class SecondPassHandler extends AbstractHandler { @Override public boolean handler() { System.out.println("SecondPassHandler进行处理...."); if (successor != null) { return successor.handler(); } return true; } } // 客户类 public class HandlerChain { private AbstractHandler firstHandler = null; private AbstractHandler lastHandler = null; public HandlerChain addHandler(AbstractHandler handler) { // 维护继承者 if (firstHandler == null) { firstHandler = handler; lastHandler = handler; } else { lastHandler.setSuccessor(handler); lastHandler = handler; } return this; } public boolean handle() { return firstHandler.handler(); } } // 测试类 public class MainTest { public static void main(String[] args) { HandlerChain handlerChain = new HandlerChain(); handlerChain.addHandler(new FirstPassHandler()).addHandler(new SecondPassHandler()); handlerChain.handle(); } } ``` - Code3 ```java class Request { String str; } class Response { String str; } // 抽象处理者 interface Filter { void doFilter(Request request, Response response, FilterChain chain); } // 具体处理者1 class HTMLFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain chain) { request.str = request.str.replaceAll("<", "[").replaceAll(">", "]") + "HTMLFilter()"; chain.doFilter(request, response); response.str += "--HTMLFilter()"; } } // 具体处理者2 class SensitiveFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain chain) { request.str = request.str.replaceAll("996", "955") + " SensitiveFilter()"; chain.doFilter(request, response); response.str += "--SensitiveFilter()"; } } // 责任链对象(维护了一个具体处理请求集合) class FilterChain { List filters = new ArrayList<>(); int index = 0; public FilterChain add(Filter f) { filters.add(f); return this; } public void doFilter(Request request, Response response) { if(index == filters.size()) return; Filter f = filters.get(index); index ++; f.doFilter(request, response, this); } } // 测试类 public class Servlet_Main { public static void main(String[] args) { Request request = new Request(); request.str = "大家好:),