行为型模式--责任链模式(Chain of Responsibility)

本文深入探讨了责任链模式的概念、实现方式及其应用案例,包括如何构建责任链、处理请求流程以及通过不同实例展示其灵活性。通过具体的Java代码实现,展示了如何在不同场景下灵活运用责任链模式。

接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。先看看关系图:

 

 

Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

[java]  view plain copy
  1. public interface Handler {  
  2.     public void operator();  
  3. }  
[java]  view plain copy
  1. public abstract class AbstractHandler {  
  2.       
  3.     private Handler handler;  
  4.   
  5.     public Handler getHandler() {  
  6.         return handler;  
  7.     }  
  8.   
  9.     public void setHandler(Handler handler) {  
  10.         this.handler = handler;  
  11.     }  
  12.       
  13. }  
[java]  view plain copy
  1. public class MyHandler extends AbstractHandler implements Handler {  
  2.   
  3.     private String name;  
  4.   
  5.     public MyHandler(String name) {  
  6.         this.name = name;  
  7.     }  
  8.   
  9.     @Override  
  10.     public void operator() {  
  11.         System.out.println(name+"deal!");  
  12.         if(getHandler()!=null){  
  13.             getHandler().operator();  
  14.         }  
  15.     }  
  16. }  
[java]  view plain copy
  1. public class Test {  
  2.   
  3.     public static void main(String[] args) {  
  4.         MyHandler h1 = new MyHandler("h1");  
  5.         MyHandler h2 = new MyHandler("h2");  
  6.         MyHandler h3 = new MyHandler("h3");  
  7.   
  8.         h1.setHandler(h2);  
  9.         h2.setHandler(h3);  
  10.   
  11.         h1.operator();  
  12.     }  
  13. }  

输出:

h1deal!
h2deal!
h3deal!

此处强调一点就是,链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

====================================================================

下面是另外一个例子:

public class Test {

	public static void main(String[] args) {

		String pass1 = "123456";

		String pass2 = "123456";

		String personId = "123456227890125678";

		String email = "chmask@163.com";

		register(pass1, pass2, personId, email);

	}

	public static void register(String pass1, String pass2, String personId, String email) {

		Filter f1 = new PasswordFilter1();

		Filter f2 = new PasswordFilter2();

		Filter f3 = new PersonIdFilter();

		Filter f4 = new EmailFilter();

		f1.setNext(f2);

		f2.setNext(f3);

		f3.setNext(f4);

		System.out.println(f1.doFilter(pass1, pass2, personId, email));

	}

}

abstract class Filter {

	Filter next = null;

	public Filter getNext() {

		return next;

	}

	public void setNext(Filter next) {

		this.next = next;

	}

	public String doFilter(String pass1, String pass2, String personId, String email) {

		if (next == null)
			return "成功";

		else
			return next.doFilter(pass1, pass2, personId, email);

	}

}

class PasswordFilter1 extends Filter {

	public String doFilter(String pass1, String pass2, String personId, String email) {

		if (!(pass1.equals(pass2)))

			return "两次密码输入不一致";

		else
			return super.doFilter(pass1, pass2, personId, email);

	}

}

class PasswordFilter2 extends Filter {

	public String doFilter(String pass1, String pass2, String personId, String email) {

		if (pass1.length() != 6)

			return "密码长度必须为6";

		else
			return super.doFilter(pass1, pass2, personId, email);

	}

}

class PersonIdFilter extends Filter {

	public String doFilter(String pass1, String pass2, String personId, String email) {

		if (personId.length() != 15 && personId.length() != 18)

			return "身份证号码非法";

		else
			return super.doFilter(pass1, pass2, personId, email);

	}

}

class EmailFilter extends Filter {

	public String doFilter(String pass1, String pass2, String personId, String email) {

		int i1 = email.indexOf("@");

		int i2 = email.indexOf(".");

		if (i1 == -1 || i2 == -1 || i2 - i1 <= 1 || i1 == 0 || i2 == email.length() - 1)

			return "email非法";

		else
			return super.doFilter(pass1, pass2, personId, email);

	}

}

 下面使用了一个责任链模式的最简单的实现。

  责任链模式涉及到的角色如下所示:

  ●  抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。

  ●  具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

源代码

  抽象处理者角色

复制代码
public abstract class Handler {
    
    /**
     * 持有后继的责任对象
     */
    protected Handler successor;
    /**
     * 示意处理请求的方法,虽然这个示意方法是没有传入参数的
     * 但实际是可以传入参数的,根据具体需要来选择是否传递参数
     */
    public abstract void handleRequest();
    /**
     * 取值方法
     */
    public Handler getSuccessor() {
        return successor;
    }
    /**
     * 赋值方法,设置后继的责任对象
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    
}
复制代码

  具体处理者角色

复制代码
public class ConcreteHandler extends Handler {
    /**
     * 处理方法,调用此方法处理请求
     */
    @Override
    public void handleRequest() {
        /**
         * 判断是否有后继的责任对象
         * 如果有,就转发请求给后继的责任对象
         * 如果没有,则处理请求
         */
        if(getSuccessor() != null)
        {            
            System.out.println("放过请求");
            getSuccessor().handleRequest();            
        }else
        {            
            System.out.println("处理请求");
        }
    }

}
复制代码

  客户端类

复制代码
public class Client {

    public static void main(String[] args) {
        //组装责任链
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler();
        handler1.setSuccessor(handler2);
        //提交请求
        handler1.handleRequest();
    }

}

 地组合职责链,实现不同的功能要求了。

  

public abstract class Handler {
    /**
     * 持有下一个处理请求的对象
     */
    protected Handler successor = null;
    /**
     * 取值方法
     */
    public Handler getSuccessor() {
        return successor;
    }
    /**
     * 设置下一个处理请求的对象
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    /**
     * 处理聚餐费用的申请
     * @param user    申请人
     * @param fee    申请的钱数
     * @return        成功或失败的具体通知
     */
    public abstract String handleFeeRequest(String user , double fee);
}

public class ProjectManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //项目经理权限比较小,只能在500以内
        if(fee < 500)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:项目经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:项目经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //超过500,继续传递给级别更高的人处理
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }
}
public class DeptManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //部门经理的权限只能在1000以内
        if(fee < 1000)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:部门经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:部门经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //超过1000,继续传递给级别更高的人处理
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }
}
public class GeneralManager extends Handler {

    @Override
    public String handleFeeRequest(String user, double fee) {
        
        String str = "";
        //总经理的权限很大,只要请求到了这里,他都可以处理
        if(fee >= 1000)
        {
            //为了测试,简单点,只同意张三的请求
            if("张三".equals(user))
            {
                str = "成功:总经理同意【" + user + "】的聚餐费用,金额为" + fee + "元";    
            }else
            {
                //其他人一律不同意
                str = "失败:总经理不同意【" + user + "】的聚餐费用,金额为" + fee + "元";
            }
        }else
        {
            //如果还有后继的处理对象,继续传递
            if(getSuccessor() != null)
            {
                return getSuccessor().handleFeeRequest(user, fee);
            }
        }
        return str;
    }

}
public class Client {

    public static void main(String[] args) {
        //先要组装责任链
        Handler h1 = new GeneralManager();
        Handler h2 = new DeptManager();
        Handler h3 = new ProjectManager();
        h3.setSuccessor(h2);
        h2.setSuccessor(h1);
        
        //开始测试
        String test1 = h3.handleFeeRequest("张三", 300);
        System.out.println("test1 = " + test1);
        String test2 = h3.handleFeeRequest("李四", 300);
        System.out.println("test2 = " + test2);
        System.out.println("---------------------------------------");
        
        String test3 = h3.handleFeeRequest("张三", 700);
        System.out.println("test3 = " + test3);
        String test4 = h3.handleFeeRequest("李四", 700);
        System.out.println("test4 = " + test4);
        System.out.println("---------------------------------------");
        
        String test5 = h3.handleFeeRequest("张三", 1500);
        System.out.println("test5 = " + test5);
        String test6 = h3.handleFeeRequest("李四", 1500);
        System.out.println("test6 = " + test6);
    }

}

 

 运行结果如下所示:

 

 

<think>我们正在讨论责任链模式Chain of Responsibility)。根据引用[1],责任链模式是一种行为设计模式,它通过将请求沿着处理者链传递来避免请求发送者和接收者之间的耦合。多个处理者对象都有机会处理请求,直到其中一个处理它为止。 引用[2]提供了一段示例代码,展示了责任链模式的实现方式。代码中定义了一个处理者基类CHandler,它包含一个指向下一个处理者的指针(m_pHandler)和一个处理请求的虚函数HandleRequest。然后定义了三个具体的处理者类(CConcreteHandler1, CConcreteHandler2, CConcreteHandler3),每个具体处理者根据自己的条件决定是否处理请求,如果不处理则传递给下一个处理者。 因此,我们可以这样介绍责任链模式责任链模式Chain of Responsibility)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。这种模式解耦了请求的发送者和接收者,允许多个对象都有机会处理请求。 责任链模式的主要组成部分: 1. 处理者(Handler):定义一个处理请求的接口,通常包含一个指向下一个处理者的引用(后继者链接)。在示例代码中,CHandler就是抽象处理者。 2. 具体处理者(Concrete Handler):实现处理请求的具体逻辑。如果自己能够处理请求,则处理;否则将请求传递给后继者。示例代码中的CConcreteHandler1、CConcreteHandler2、CConcreteHandler3就是具体处理者。 责任链模式的特点: - 降低了对象之间的耦合度:请求发送者无需知道哪个对象会处理其请求。 - 增强了系统的可扩展性:可以动态地增加或修改处理者链。 - 增强了给对象指派职责的灵活性:通过改变链内的成员或者调整次序,可以动态地改变处理流程。 - 责任链简化了对象之间的连接:每个处理者只需保持一个指向其后继者的引用,而不需保持所有处理者的引用。 - 责任分担:每个处理者只需处理自己能够处理的请求,将不能处理的请求传递给下一个处理者,符合类的单一职责原则。 但是,责任链模式也有缺点: - 不能保证请求一定被处理:如果链中没有合适的处理者,请求可能到达链的末端也没有被处理。 - 对于较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。 - 调试时可能比较复杂,特别是链条较长时,逻辑可能不易追踪。 应用场景: 责任链模式适用于以下情况: - 有多个对象可以处理同一个请求,具体哪个对象处理该请求在运行时自动确定。 - 需要动态指定一组对象处理请求,或者需要动态添加、删除处理者。 - 在不明确指定接收者的情况下,向多个对象中的一个提交请求。 下面我们用一段标准化的代码示例(使用C++)来展示责任链模式: ```cpp #include <iostream> // 抽象处理者 class Handler { public: virtual ~Handler() {} void SetNext(Handler* next) { next_ = next; } virtual void HandleRequest(int request) const = 0; protected: Handler* next_ = nullptr; }; // 具体处理者A class ConcreteHandlerA : public Handler { public: void HandleRequest(int request) const override { if (request < 10) { std::cout << "ConcreteHandlerA handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 具体处理者B class ConcreteHandlerB : public Handler { public: void HandleRequest(int request) const override { if (request >= 10 && request < 20) { std::cout << "ConcreteHandlerB handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 具体处理者C class ConcreteHandlerC : public Handler { public: void HandleRequest(int request) const override { if (request >= 20) { std::cout << "ConcreteHandlerC handled request " << request << "\n"; } else if (next_ != nullptr) { next_->HandleRequest(request); } } }; // 客户端代码 int main() { ConcreteHandlerA handlerA; ConcreteHandlerB handlerB; ConcreteHandlerC handlerC; handlerA.SetNext(&handlerB); handlerB.SetNext(&handlerC); // 创建一系列请求 int requests[] = {5, 15, 25}; for (int req : requests) { handlerA.HandleRequest(req); } return 0; } ``` 在这个示例中,我们创建了三个具体处理者(ConcreteHandlerA、ConcreteHandlerB、ConcreteHandlerC),它们分别处理不同范围的请求。客户端将请求发送给链中的第一个处理者(handlerA),然后请求沿着链传递直到被处理。 责任链模式在现实中的应用包括: - 事件处理系统(如GUI中的事件冒泡) - 日志记录器(不同级别的日志由不同的记录器处理) - Web框架中的中间件(每个中间件可以处理请求并决定是否传递给下一个) - 异常处理(try-catch块可以看作是一个责任链) 相关问题: 1. 责任链模式在哪些实际框架或库中有应用? 2. 如何处理责任链中请求未被处理的情况? 3. 责任链模式和状态模式有什么区别? 4. 如何动态地修改责任链的结构? </think>### 责任链模式Chain of Responsibility)介绍 责任链模式Chain of Responsibility)是一种**行为型设计模式**,核心思想是将多个处理对象连接成一条链,请求沿链传递直至被处理。这种模式解耦了请求发送者和接收者,允许多个对象都有机会处理请求。以下是详细解析: --- #### 一、核心结构与原理 1. **处理者(Handler)抽象类** 定义处理请求的接口,包含: - 指向下一个处理者的引用(`m_pHandler`) - 处理请求的虚方法(`HandleRequest()`) ```cpp class Handler { public: void SetNext(Handler* next) { m_pNext = next; } virtual void HandleRequest(int request) = 0; protected: Handler* m_pNext = nullptr; // 后继处理者 }; ``` 2. **具体处理者(Concrete Handler)** 实现具体的处理逻辑,若无法处理则转发给下一个处理者: ```cpp class ConcreteHandlerA : public Handler { public: void HandleRequest(int request) override { if (request < 10) std::cout << "HandlerA processed request: " << request << "\n"; else if (m_pNext) m_pNext->HandleRequest(request); // 传递给下一个 } }; ``` 3. **客户端调用** 构建处理链并发送请求: ```cpp int main() { Handler* handlerA = new ConcreteHandlerA(); Handler* handlerB = new ConcreteHandlerB(); handlerA->SetNext(handlerB); // 设置责任链 handlerA->HandleRequest(15); // 请求在链上传递 } ``` --- #### 二、关键特性 1. **解耦性** 请求发送者无需知道具体处理者,只需向链首提交请求[^1]。 2. **动态扩展** 可随时增减或调整处理者节点(如添加 `ConcreteHandlerC`)。 3. **处理灵活性** 请求可能被链中任意节点处理,也可能未被任何节点处理。 4. **符合开闭原则** 新增处理者无需修改现有代码。 --- #### 三、适用场景 1. **多级请求处理** 如审批流程(员工→经理→CEO)、日志级别过滤(DEBUG→INFO→ERROR)。 2. **动态指定处理对象** 例如中间件管道(如Express.js的中间件链)。 3. **未知接收者的场景** 如GUI事件冒泡机制(控件→父容器→窗口)。 --- #### 四、优缺点分析 | **优点** | **缺点** | |-----------------------------------|--------------------------| | 降低耦合度(请求发送者与接收者分离) | 请求可能未被处理(链尾无兜底) | | 动态增删处理节点 | 长链可能影响性能 | | 简化对象间连接(单向链式传递) | 调试复杂度较高 | --- #### 五、与其他模式的关系 - **与装饰器模式** 两者都基于链式结构,但装饰器模式重在**增强功能**,责任链重在**分发请求**。 - **与状态模式** 状态模式通过状态转移改变行为,责任链通过固定链条传递请求。 --- ### 相关问题 1. 责任链模式如何处理请求未被任何节点处理的情况? 2. 在实际框架(如Spring、Express.js)中责任链模式有哪些典型应用? 3. 如何在责任链模式中实现请求的优先级处理? 4. 责任链模式与命令模式结合会产生什么效果? [^1]: 责任链模式通过对象链解耦请求发送者和接收者[^1]。 [^2]: 具体处理者通过条件判断决定是否处理请求[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值