Chain of Responsibility Patterns

GoF定义:通过让多个(超过一个)对象来处理请求实现请求发送者和接收者的耦合度。接收者(对象)的链会被传入请求,直到有一个对象处理此请求

概念

这里按序列方式处理对象,会有一个源来执行这个过程。我们会创建一个接收链,其中的每个对象都有逻辑来处理不同类型的命令对象。在一个处理过程完成后,如果这个对象并没有被处理完成,那么将这个对象发送到接收链的下一个对象。我们可以在任何时候从链尾添加对象

例子

现实世界:在一个企业中,有客服会将用户的反馈收集起来给到对应的部门,并不是每个部门都直接处理问题,当他们确定了问题的性质之后,会继续把问题抛向更适合解决的部门
代码世界:假设有一个应用处理电子邮件和传真,对应各有一个错误的处理器(handler),它们只会处理对应的错误而不关心其它类型的错误。我们会将这两个handler连在一起,如果发现新类型的错误处理器,可以将其连在后面。这个链路会在请求被解决或者链路终结时停止

展示

代码

public class ChainOfResponsibilityPatternEx
{
    public static void main(String[] args)
    {
        System.out.println("***Chain of Responsibility Pattern Demo***\n");
        //Making the chain first: IssueRaiser->FaxErrorhandler->EmailErrorHandler
        IReceiver faxHandler, emailHandler;
        //end of chain
        emailHandler = new EmailErrorHandler(null);
        //fax handler is before email
        faxHandler = new FaxErrorHandler(emailHandler);
        //starting point: raiser will raise issues and set the first handler
        IssueReceiver raiser = new IssueReceiver (faxHandler);
        Message m1 = new Message("Fax is reaching late to the destination", MessagePriority.Normal);
        Message m2 = new Message("Email is not going", MessagePriority.High);
        Message m3 = new Message("In Email, BCC field is disabled occasionally", MessagePriority.Normal);
        Message m4 = new Message("Fax is not reaching destination", MessagePriority.High);
        raiser.raiseMessage(m1);
        raiser.raiseMessage(m2);
        raiser.raiseMessage(m3);
        raiser.raiseMessage(m4);
    }
}

enum MessagePriority
{
    Normal, High
}

class Message
{
    public String text;
    public MessagePriority priority;

    public Message(String text, MessagePriority priority)
    {
        this.text = text;
        this.priority = priority;
    }
}

interface IReceiver
{
    Boolean processMessage(Message message);
}

class IssueReceiver
{
    public IReceiver setFirstReceiver;

    public IssueReceiver(IReceiver setFirstReceiver)
    {
        this.setFirstReceiver = setFirstReceiver;
    }

    public void raiseMessage(Message message)
    {
        if (setFirstReceiver != null)
        {
            setFirstReceiver.processMessage(message);
        }
    }
}

class FaxErrorHandler implements IReceiver
{
    private IReceiver nextReceiver;

    public FaxErrorHandler(IReceiver nextReceiver)
    {
        this.nextReceiver = nextReceiver;
    }

    @Override
    public Boolean processMessage(Message message)
    {
        if (message.text.contains("Fax"))
        {
            System.out.println("FaxErrorHandler processed "+ message.priority+ "priority issue: "+ message.text);
            return true;
        }
        else
        {
            if (nextReceiver != null)
            {
                nextReceiver.processMessage(message);
            }
        }
        return false;
    }
}

class EmailErrorHandler implements IReceiver
{
    private IReceiver nextReceiver;

    public EmailErrorHandler(IReceiver nextReceiver)
    {
        this.nextReceiver = nextReceiver;
    }

    @Override
    public Boolean processMessage(Message message)
    {
        if (message.text.contains("Email"))
        {
            System.out.println("EmailErrorHandler processed "+ message.priority + "priority issue: "+ message.text);
            return true;
        }
        else
        {
            if (nextReceiver != null)
            {
                nextReceiver.processMessage(message);
            }
        }
        return false;
    }
}

Note

  1. 当我们在不指定接收者的情况下发送了请求,并且希望任意一个接收者可以处理这个请求,此时可以使用这个模式
  2. 在有多个接收者可以处理某个请求,但是接收者不知道优先级的情况下,我们可以使用这个模式来解决此问题
  3. 运行时处理某个对象(请求)的能力
  4. 可以定义新链,也可以扩展旧链
  5. 有时我们希望有一个自动转发请求的机制,而不需要自己写特定的转发规则(Smalltalk’s doesnotUnderstand是一个典型例子--有时间看过之后再来补充)

思考

这个模式的用法基本上上一节书里都说完了,我个人感觉这个模式的核心在于请求必须是多种(3、4种及以上)类型的值得使用这个模式

posted on 2020-12-12 22:57  老鼠不上树  阅读(48)  评论(0)    收藏  举报