设计模式之责任链及策略模式

责任链模式

Java中的责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,允许你将请求沿着处理者链进行发送。请求会沿链传递,直到某个处理者对象负责处理它。这种模式的主要优点是请求的发送者和接收者之间不需要知道对方的详细信息,请求的流程也可以动态地进行调整。 责任链模式通常用于过滤或处理请求的场景,例如日志记录、权限验证等。

责任链模式的关键组成部分:

  • Handler(处理者):一个处理请求的接口,声明了处理请求的方法,并且有具体的实现。
  • ConcreteHandler(具体处理者):实现了Handler接口的处理者,它们在处理请求时可以选择处理请求、传递给下一个处理者或者不处理。
  • Client(客户端):创建并配置责任链,将请求发送到链中的第一个处理者。
  • Request(请求):需要被处理的请求对象。

基本实现步骤:

  1. 定义一个处理者接口,包括一个处理方法的声明。
  2. 创建具体处理者类,实现处理者接口,并重写处理方法。
  3. 创建一个链式处理者类,管理责任链中的处理者,通常会包含一个指向下一个处理者的引用。
  4. 配置责任链,将处理者连接起来形成一个链。
  5. 客户端发送请求到责任链中的第一个处理者。

示例代码:

typescript 复制代码
// 处理者接口
interface Handler {
    void setNext(Handler handler);
    void handleRequest(String request);
}
// 具体处理者A
class ConcreteHandlerA implements Handler {
    private Handler nextHandler;
    @Override
    public void setNext(Handler handler) {
        this.nextHandler = handler;
    }
    @Override
    public void handleRequest(String request) {
        if ("A".equals(request)) {
            System.out.println("ConcreteHandlerA 处理了请求 " + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}
// 具体处理者B
class ConcreteHandlerB implements Handler {
    private Handler nextHandler;
    @Override
    public void setNext(Handler handler) {
        this.nextHandler = handler;
    }
    @Override
    public void handleRequest(String request) {
        if ("B".equals(request)) {
            System.out.println("ConcreteHandlerB 处理了请求 " + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}
// 具体处理者C
class ConcreteHandlerC implements Handler {
    private Handler nextHandler;
    @Override
    public void setNext(Handler handler) {
        this.nextHandler = handler;
    }
    @Override
    public void handleRequest(String request) {
        if ("C".equals(request)) {
            System.out.println("ConcreteHandlerC 处理了请求 " + request);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}
// 链式处理者
class Chain {
    private Handler handler;
    public Chain(Handler handler) {
        this.handler = handler;
    }
    public void setNext(Handler handler) {
        this.handler.setNext(handler);
    }
    public void handleRequest(String request) {
        handler.handleRequest(request);
    }
}
// 客户端
public class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();
        handlerA.setNext(handlerB);
        handlerB.setNext(handlerC);
        Chain chain = new Chain(handlerA);
        chain.handleRequest("A");
        chain.handleRequest("B");
        chain.handleRequest("C");
        chain.handleRequest("D");
    }
}

在上述代码中,我们定义了三个具体处理者,它们按照顺序形成了责任链。客户端创建并配置了责任链,并将请求发送给链中的第一个处理者。在运行时,请求会沿着责任链传递,直到被某个处理者处理。 在实际应用中,责任链模式可以非常灵活地处理各种请求,并且可以根据需要轻松地添加或删除处理者。此外,责任链模式还可以实现类似于策略模式的动态切换行为,因为处理者可以很容易地被替换或重新排列。 责任链模式也有一些潜在的问题,比如如果处理者链过长,可能会导致性能下降,因为每个处理者都需要被遍历一遍。此外,如果责任链中的处理者逻辑过于复杂,可能会使得代码难以理解和维护。 在设计系统时,责任链模式适用于那些需要多个对象共同处理一个请求的场景,而且这些对象之间的职责关系不是很明显,或者需要根据不同的条件动态地选择处理者。通过使用责任链模式,可以将请求的发送和接收解耦,从而提高系统的灵活性和可扩展性。

策略模式

策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时根据需要定义一系列算法,将每个算法封装起来,并使它们可以相互替换。该模式由以下主要部分组成:

  1. 策略接口(Strategy) :定义所有支持的算法的公共操作和属性。
  2. 具体策略(Concrete Strategy) :实现策略接口的类,定义具体的算法。
  3. 上下文(Context) :使用策略对象的类,它可以根据需要切换策略。
  4. 客户端(Client) :创建上下文和策略对象,并设置上下文使用的策略。

为什么使用策略模式

  • 在一个算法族中,选择算法应该可以在运行时进行,且算法族中的算法易于切换。
  • 需要使用不同算法的一系列问题,而这些问题可以使用相同的接口来解决。
  • 算法应该独立于使用它们的客户。

实现步骤

  1. 定义策略接口。
  2. 实现具体的策略类。
  3. 设计上下文来使用策略对象。
  4. 客户端创建上下文和策略对象,并设置上下文使用的策略。

示例

下面是一个简单的Java示例,说明如何实现策略模式:

csharp 复制代码
// 策略接口
interface Strategy {
    void execute();
}
// 具体策略A
class ConcreteStrategyA implements Strategy {
    public void execute() {
        System.out.println("执行策略A");
    }
}
// 具体策略B
class ConcreteStrategyB implements Strategy {
    public void execute() {
        System.out.println("执行策略B");
    }
}
// 上下文
class Context {
    private Strategy strategy;
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
    public void executeStrategy() {
        strategy.execute();
    }
}
// 客户端
public class StrategyPatternDemo {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStrategyA());
        context.executeStrategy();
        context.setStrategy(new ConcreteStrategyB());
        context.executeStrategy();
    }
}

在这个例子中,Strategy 接口有两个实现 ConcreteStrategyAConcreteStrategyBContext 类使用策略对象,并在运行时可以切换策略。StrategyPatternDemo 类是客户端,它创建上下文和策略对象,并调用 executeStrategy() 方法来执行相应的算法。 策略模式提供了一种非常灵活的方式来选择和切换算法,而且可以轻松地添加新的策略。这使得它成为处理算法族和需要在运行时选择算法的一个非常强大的工具。

相关推荐
孑么30 分钟前
GDPU Android移动应用 重点习题集
android·xml·java·okhttp·kotlin·android studio·webview
未命名冀1 小时前
微服务面试相关
java·微服务·面试
Heavydrink1 小时前
ajax与json
java·ajax·json
阿智智1 小时前
纯手工(不基于maven的pom.xml、Web容器)连接MySQL数据库的详细过程(Java Web学习笔记)
java·mysql数据库·纯手工连接
fangxiang20082 小时前
spring boot 集成 knife4j
java·spring boot
王先生技术栈2 小时前
思维导图,Android版本实现
java·前端
生如夏花℡2 小时前
JAVA学习记录3
java·学习·idea
{⌐■_■}2 小时前
【gRPC】对称与非对称加解密和单向TLS与双向TLS讲解与go案例
java·servlet·golang
敲代码养活全家3 小时前
ElasticsearchJavaClient工具类分析
java·elasticsearch·搜索引擎
蟹黄堡在逃员工3 小时前
消息队列MQ(一)
java·后端