【地铁上的设计模式】--行为型模式:职责链模式

2023-05-07 21:27:06 浏览数 (1)

从这篇文章开始,我们将进入到设计模式的最后一大类行为模式

什么是行为模式

行为模式是面向对象编程中,一组用于处理对象间交互的设计模式。行为模式主要关注的是对象之间的责任分配和行为控制。 以下是11种常见的行为模式简介:

  1. 模板方法模式(Template Method Pattern) 模板方法模式定义了一个算法框架,将一些步骤的具体实现交由子类去完成,从而使得算法框架和步骤的具体实现分离开来。
  2. 策略模式(Strategy Pattern) 策略模式定义了一系列算法,将每个算法封装成独立的对象,使它们可以互换。
  3. 观察者模式(Observer Pattern) 观察者模式定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
  4. 迭代器模式(Iterator Pattern) 迭代器模式提供了一种统一的方式来遍历不同类型的集合对象,使得客户端可以访问集合对象的元素而不必关心底层实现。
  5. 职责链模式(Chain of Responsibility Pattern) 职责链模式通过将请求的发送者和接收者解耦,构成一条责任链,将请求在责任链中传递直到有一个接收者处理请求。
  6. 命令模式(Command Pattern) 命令模式将一个请求封装成一个对象,从而可以将请求的发出者和请求的接收者解耦。
  7. 备忘录模式(Memento Pattern) 备忘录模式用于在不破坏封装性的前提下,将一个对象的状态保存下来,以便于之后可以将对象恢复到之前的状态。
  8. 状态模式(State Pattern) 状态模式用于解决对象在不同状态下的行为差异问题,将对象在不同状态下的行为封装成独立的类,从而使得状态的改变不会影响到行为的执行。
  9. 访问者模式(Visitor Pattern) 访问者模式定义了一种将算法与对象结构分离的方式,可以在不修改对象结构的情况下定义新的操作。
  10. 中介者模式(Mediator Pattern) 中介者模式用于解决对象之间的复杂交互问题,将复杂的交互逻辑封装到中介者对象中,从而使得对象之间的关系更加简单明了。
  11. 解释器模式(Interpreter Pattern) 解释器模式用于定义一种语言并解释执行,将语言的语法规则定义成类层次结构,从而可以灵活地添加新的语法规则。

下面我们来看一下职责链模式

什么是职责链模式

职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。该模式构成了一条链,请求在这条链上传递,直到被处理为止。

职责链模式的核心思想是将请求和处理分离开来,形成一条处理链。请求会从链的头部传入,每个处理者会判断是否有权处理请求,如果有,则处理请求,否则将请求传递给链中的下一个处理者。这样,请求就会在链上流动,直到有一个处理者处理请求或者请求到达链尾时被丢弃。

职责链模式通常包含以下角色:

  1. 抽象处理者(Handler):定义一个处理请求的接口,并维护一个指向下一个处理者的引用。
  2. 具体处理者(ConcreteHandler):实现抽象处理者接口,处理它所负责的请求,如果无法处理则将请求传递给下一个处理者。
  3. 客户端(Client):创建处理链,并将请求发送到链的第一个处理者。

职责链模式有助于降低系统的耦合度,可以方便地增加或删除处理者,对系统的灵活性和可扩展性有很大的帮助。它也有一些缺点,比如可能导致请求处理不确定,降低系统的性能等。

如何实现职责链模式

职责链模式的实现步骤如下:

  1. 定义一个处理请求的抽象类或接口,其中包含一个处理请求的方法和一个设置下一个处理者的方法;
  2. 定义一系列具体的处理者类,实现处理请求的方法,并在需要的情况下将请求转发给下一个处理者;
  3. 将这些具体的处理者组织成一条职责链,例如使用一个链表或数组来保存处理者,并在构建时将它们连接起来;
  4. 当有请求需要处理时,将请求传递给职责链的头部,从头部开始依次调用处理者,直到有一个处理者能够处理该请求或职责链的末尾被达到为止。

Java实现 好的,以下是Java实现职责链模式的示例代码,以及代码的讲解:

代码语言:javascript复制
// 抽象处理器
public abstract class Handler {
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(Request request);
}

// 具体处理器A
public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            System.out.println("Handled by ConcreteHandlerA");
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

// 具体处理器B
public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            System.out.println("Handled by ConcreteHandlerB");
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

// 请求
public class Request {
    private RequestType type;

    public Request(RequestType type) {
        this.type = type;
    }

    public RequestType getType() {
        return type;
    }

    public void setType(RequestType type) {
        this.type = type;
    }
}

// 请求类型
public enum RequestType {
    TYPE_A,
    TYPE_B
}

职责链模式的关键在于把请求的处理逻辑拆分成一系列处理器,每个处理器都可以处理请求,如果当前处理器无法处理该请求,则把该请求传递给下一个处理器。这样就形成了一个处理器链。 以上面的示例代码为例,职责链中包含两个具体处理器ConcreteHandlerA和ConcreteHandlerB,它们分别处理类型为TYPE_A和TYPE_B的请求,如果当前处理器无法处理请求,则把该请求传递给下一个处理器。如果请求的类型不是TYPE_A或TYPE_B,则不做任何处理。 当客户端发送一个请求时,请求首先传递给ConcreteHandlerA进行处理,如果ConcreteHandlerA无法处理该请求,则把该请求传递给ConcreteHandlerB进行处理。如果ConcreteHandlerB还是无法处理该请求,则请求就会被丢弃,因为没有处理器能够处理该请求。

C#实现 以下是在 C# 中实现职责链模式的示例代码:

代码语言:javascript复制
// 定义一个处理请求的接口
public interface IHandler
{
    IHandler SetNext(IHandler handler);
    object Handle(object request);
}

// 具体的处理器
public class ConcreteHandlerA : IHandler
{
    private IHandler _nextHandler;

    public IHandler SetNext(IHandler handler)
    {
        _nextHandler = handler;
        return handler;
    }

    public object Handle(object request)
    {
        if (request is string s && s.Equals("A"))
        {
            return $"ConcreteHandlerA: {s}";
        }
        else
        {
            return _nextHandler?.Handle(request);
        }
    }
}

// 另一个具体的处理器
public class ConcreteHandlerB : IHandler
{
    private IHandler _nextHandler;

    public IHandler SetNext(IHandler handler)
    {
        _nextHandler = handler;
        return handler;
    }

    public object Handle(object request)
    {
        if (request is string s && s.Equals("B"))
        {
            return $"ConcreteHandlerB: {s}";
        }
        else
        {
            return _nextHandler?.Handle(request);
        }
    }
}

// 客户端代码
public class Client
{
    public static void Main()
    {
        // 组合处理器链
        var handlerA = new ConcreteHandlerA();
        var handlerB = new ConcreteHandlerB();
        handlerA.SetNext(handlerB);

        // 发送请求
        var result = handlerA.Handle("B");
        Console.WriteLine(result);
    }
}

在这个示例中,我们定义了 IHandler 接口和两个具体的处理器 ConcreteHandlerAConcreteHandlerBIHandler 接口定义了处理请求的方法 Handle 和设置下一个处理器的方法 SetNext。具体的处理器实现了 IHandler 接口,并根据自己的处理能力决定是否处理该请求,如果不能处理,则将请求转发给下一个处理器。 在客户端代码中,我们首先组合了处理器链,然后发送请求。在这个示例中,请求是一个字符串 "B",首先会被发送到 ConcreteHandlerA,由于它无法处理 "B" 请求,因此将请求转发给下一个处理器 ConcreteHandlerB,最终得到了处理结果。

Tip:需要注意的是,在实现职责链模式时,处理器链的组合方式可以是链表、数组、树等数据结构,具体实现方式会根据业务场景的不同而有所差异。

总结

职责链模式是一种行为型设计模式,它能够将请求发送者和接收者解耦并且使得请求沿着一个链进行传递。职责链模式是一条链,每个节点处理请求,如果自己处理不了,就传递给下一个节点去处理。这个模式非常适合处理在运行时可以决定由哪些对象来处理请求的情况。职责链模式的优点是可以简化对象的相互连接,降低耦合度,增加了灵活性,使得请求的发送者不需要知道哪个接收者能够处理该请求。缺点是当链太长或者处理时间过长时,会影响系统性能,容易出现循环调用,导致系统崩溃等问题。 在实际开发中,职责链模式的应用场景很多,比如:请求需要多个对象进行处理,而不确定哪个对象能够处理请求;希望动态指定可以处理请求的对象集合;希望在不明确接收者的情况下,向多个对象中的一个或多个发送请求等。 总之,职责链模式通过将请求发送者和接收者解耦,可以更加灵活地处理请求。在实际开发中,应该根据具体的场景来选择是否使用该模式,以充分发挥其优点,同时避免潜在的缺点。

0 人点赞