Паттерн цепочка обязанностей java пример

Chain of Responsibility Design Pattern

The Chain of Responsibility is known as a behavioral pattern. The main objective of this pattern is that it avoids coupling the sender of the request to the receiver, giving more than one object the opportunity to handle the request. The core logic defined by GoF is :

"Gives more than one object an opportunity to handle a request by linking receiving objects together."

Chain of Responsibility allows a number of classes to attempt to handle a request, independently of any other object along the chain. Once the request is handled, it completes it’s journey through the chain.

Extra handlers can be added or removed from chain without modifying the logic inside any of concrete handler.

Sections in this post: Suggested usage Participants in the solution Sample problem to be solved Proposed solution Class diagram of participants Sourcecode of participants Test the application Download sourecode link Reference implementations in JDK

Suggested usage

This pattern is recommended when multiple objects can handle a request and the handler doesn’t have to be a specific object. Also, handler is determined at runtime. Please note that that a request not handled at all by any handler is a valid use case.

For example, event handling mechanism in windows OS where events can be generated from either mouse, keyboard or some automatic generated events. All such events can be handled by multiple handlers and correct handler is found on runtime.

More general exampe can be a service request to call center. This request can be handled at front desk level, supervisor level or any higher level. Correct handler of request is only known at runtime when request is traversing at various levels. We will solve this scenario in this post.

Читайте также:  Php path variable windows

Participants in the solution

1) Handler : This can be an interface which will primarily recieve the request and dispatches the request to chain of handlers. It has reference of only first handler in the chain and does not know anything about rest of the handlers.

2) Concrete handlers : These are actual handlers of the request chained in some sequential order.

3) Client : Originator of request and this will access the handler to handle it.

Sample problem to be solved

The problem statement is to design a system for support service system consisting of front desk, supervisor, manager and director. Any client can call to front desk and will ask for a solution. If front desk is able to solve the issue, it will; otherwise will pass to supervisor. Similarly, supervisor will try to solve the issue and if he is able to then he will solve; else pass to manager. Same way, manager will either solve the issue or pass to director. Director will either solve the issue or reject it.

Proposed solution

Above problem is a good candidate for using chain of responsibility pattern. We can define the handler at each level i.e. support desk, supervisor, manager and director. Then we can define a chain for handling the support request. This chain must follow the sequence:

Support desk > supervisor > manager > director

Above chain can be managed using programmatic solutions in java also, but in this tutorial i am using spring for injecting the dependencies and thus forming this chain. Also, System will first assign the request to front desk only.

Class diagram of participants

I have draw the structure of all entities involved in the solution as below.

chainofresponsibility_classdiagram-2377740

Sourcecode of participants

Below is the sourcecode of all participants involved in support service implementation using chain of responsibility design pattern:

ServiceLevel.java

package com.howtodoinjava; public enum ServiceLevel

ServiceRequest.java

package com.howtodoinjava.data; import com.howtodoinjava.ServiceLevel; public class ServiceRequest < private ServiceLevel type; private String conclusion = null; public ServiceLevel getType() < return type; >public void setType(ServiceLevel type) < this.type = type; >public String getConclusion() < return conclusion; >public void setConclusion(String conclusion) < this.conclusion = conclusion; >>

SupportServiceItf.java

package com.howtodoinjava.handler; import com.howtodoinjava.data.ServiceRequest; public interface SupportServiceItf

SupportService.java

package com.howtodoinjava.handler; import com.howtodoinjava.data.ServiceRequest; public class SupportService implements SupportServiceItf < private SupportServiceItf handler = null; public SupportServiceItf getHandler() < return handler; >public void setHandler(SupportServiceItf handler) < this.handler = handler; >@Override public void handleRequest(ServiceRequest request) < handler.handleRequest(request); >>

FrontDeskSupport.java

package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class FrontDeskSupport implements SupportServiceItf < private SupportServiceItf next = null; public SupportServiceItf getNext() < return next; >public void setNext(SupportServiceItf next) < this.next = next; >@Override public void handleRequest(ServiceRequest service) < if(service.getType() == ServiceLevel.LEVEL_ONE) < service.setConclusion("Front desk solved level one reuqest !!"); >else < if(next != null)< next.handleRequest(service); >else < throw new IllegalArgumentException("No handler found for :: " + service.getType()); >> > >

SupervisorSupport.java

package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class SupervisorSupport implements SupportServiceItf < private SupportServiceItf next = null; public SupportServiceItf getNext() < return next; >public void setNext(SupportServiceItf next) < this.next = next; >@Override public void handleRequest(ServiceRequest request) < if(request.getType() == ServiceLevel.LEVEL_TWO) < request.setConclusion("Supervisor solved level two reuqest !!"); >else < if(next != null)< next.handleRequest(request); >else < throw new IllegalArgumentException("No handler found for :: " + request.getType()); >> > >

ManagerSupport.java

package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class ManagerSupport implements SupportServiceItf < private SupportServiceItf next = null; public SupportServiceItf getNext() < return next; >public void setNext(SupportServiceItf next) < this.next = next; >@Override public void handleRequest(ServiceRequest request) < if(request.getType() == ServiceLevel.LEVEL_THREE) < request.setConclusion("Manager solved level three reuqest !!"); >else < if(next != null)< next.handleRequest(request); >else < throw new IllegalArgumentException("No handler found for :: " + request.getType()); >> > >

DirectorSupport.java

package com.howtodoinjava.handler; import com.howtodoinjava.ServiceLevel; import com.howtodoinjava.data.ServiceRequest; public class DirectorSupport implements SupportServiceItf < private SupportServiceItf next = null; public SupportServiceItf getNext() < return next; >public void setNext(SupportServiceItf next) < this.next = next; >@Override public void handleRequest(ServiceRequest request) < if(request.getType() == ServiceLevel.LEVEL_FOUR) < request.setConclusion("Director solved level four reuqest !!"); >else < if(next != null)< next.handleRequest(request); >else < request.setConclusion("You problem is none of our business"); throw new IllegalArgumentException("You problem is none of our business :: " + request.getType()); >> > >

applicationConfig.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop/ http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee/ http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang/ http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx/ http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util/ http://www.springframework.org/schema/util/spring-util.xsd"> <bean <property name="handler" ref="frontDeskSupport"></property> </bean> <bean <property name="next" ref="supervisorSupport"></property> </bean> <bean <property name="next" ref="managerSupport"></property> </bean> <bean <property name="next" ref="directorSupport"></property> </bean> <bean aria-hidden="true" height="16" version="1.1" viewbox="0 0 16 16" width="16">

Test the application

I will pass various level of support requests down the chain and they will be handled by correct level. Any invalid request will be rejected as planned for.

package com.howtodoinjava; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.howtodoinjava.data.ServiceRequest; import com.howtodoinjava.handler.SupportService; public class TestChainOfResponsibility < public static void main(String[] args) < ApplicationContext context = new ClassPathXmlApplicationContext("application-config.xml"); SupportService supportService = (SupportService) context.getBean("supportService"); ServiceRequest request = new ServiceRequest(); request.setType(ServiceLevel.LEVEL_ONE); supportService.handleRequest(request); System.out.println(request.getConclusion()); request = new ServiceRequest(); request.setType(ServiceLevel.LEVEL_THREE); supportService.handleRequest(request); System.out.println(request.getConclusion()); request = new ServiceRequest(); request.setType(ServiceLevel.INVALID_REQUEST); supportService.handleRequest(request); System.out.println(request.getConclusion()); >> <strong>Output:</strong> Front desk solved level one reuqest !! Manager solved level three reuqest !! Exception in thread "main" java.lang.IllegalArgumentException: You problem is none of our business :: INVALID_REQUEST

To download the sourecode of above example application, click on below link.

Reference implementations in JDK

The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain.

If the logger is currently enabled for the given message level then the given message is forwarded to all the registered output Handler objects.

I hope that this post post has added some knowledge in your understanding of chain of responsibility pattern. If you have any query, post a comment.

Happy Learning !!

Источник

Оцените статью