Responsibility chain model
definition:
- It is defined in the design pattern as follows: multiple objects have the opportunity to process the request, so as to avoid the coupling relationship between the sender and receiver of the request. Connect these objects into a chain and pass the request along the chain until an object processes it.
Note: responsibility chain mode is also called responsibility chain mode.
In the responsibility chain mode, customers only need to send the request to the responsibility chain. They don't need to care about the processing details of the request and the transmission process of the request. The request will be transmitted automatically. Therefore, the responsibility chain decouples the sender of the request from the handler of the request.
form:
- Abstract Handler role:
Define an interface for processing requests, including abstract processing methods and a subsequent connection. - Concrete Handler role:
Implement the processing method of the abstract handler to judge whether the request can be processed. If the request can be processed, process it. Otherwise, transfer the request to its successor. - Client role: create processing chain:
And submit the request to the specific handler object of the chain head. It doesn't care about the processing details and the transmission process of the request.
Case 1
Demand;
- In the responsibility chain mode, there are multiple objects, and each object holds a reference to the next object. In this way, a chain will be formed, and the request will be passed on the chain until an object decides to process the request
- However, the sender does not know which object will handle the request in the end. Therefore, the responsibility chain mode can be implemented to dynamically adjust the system while concealing the client
Abstracthandler class provides get and set methods to facilitate MyHandle class to set and modify reference objects. MyHandle class is the core. After instantiation, a series of mutually held objects are generated to form a chain.
Abstract Handler interface: Handler
interface Handler { public void operator(); }
Abstract handler role: AbstractHandler
abstract class AbstractHandler { private Handler handler; public Handler getHandler() { return handler; } public void setHandler(Handler handler) { this.handler = handler; } }
Specific handler role: MyHandler
class MyHandler extends AbstractHandler implements Handler { private String name; public MyHandler(String name) { this.name = name; } @Override public void operator() { System.out.println(name+"deal!"); if(getHandler()!=null){ getHandler().operator(); } } }
Customer role creation processing chain: main
public class Test01 { public static void main(String[] args) { MyHandler h1 = new MyHandler("h1"); MyHandler h2 = new MyHandler("h2"); MyHandler h3 = new MyHandler("h3"); h1.setHandler(h2); h2.setHandler(h3); h1.operator(); } }
- It is emphasized here that the request on the link can be a chain, a tree or a ring. The pattern itself does not restrict this, and we need to implement it ourselves,
- At the same time, commands can only be passed from one object to another at a time, not to multiple objects.
Case 2: simulate servlet Filter
Requirement: filter the information
- Filter the request from the network and the response from the server
- For the request, filter 1 and filter 2 shall be added in order
- Filter the response according to filter 2 and filter 1
Method 1:
import java.util.ArrayList; import java.util.List; public class Servlet_Main01 { public static void main(String[] args) { Request request = new Request(); request.str = "hello everyone:),<script>,Welcome to visit mashibing.com ,Everybody is 996 "; Response response = new Response(); response.str = "response"; FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter()); chain.doFilter(request, response); System.out.println(request.str); System.out.println(response.str); } } interface Filter { boolean doFilter(Request request, Response response); } class HTMLFilter implements Filter { @Override public boolean doFilter(Request request, Response response) { request.str = request.str.replaceAll("<", "[").replaceAll(">", "]"); response.str += "--HTMLFilter()"; return true; } } class Request { String str; } class Response { String str; } class SensitiveFilter implements Filter { @Override public boolean doFilter(Request request, Response response) { request.str = request.str.replaceAll("996", "955"); response.str += "--SensitiveFilter()"; return true; } } class FilterChain implements Filter { List<Filter> filters = new ArrayList<>(); public FilterChain add(Filter f) { filters.add(f); return this; } public boolean doFilter(Request request, Response response) { for(Filter f : filters ){ f.doFilter(request, response); } return true; } }
result;
- request: HTMLFilter first, then SensitiveFilter
- response: HTMLFilter first, then SensitiveFilter
Method 2:
Process the record of adding location in filterChain, and add the third parameter in filter
import java.util.ArrayList; import java.util.List; public class Servlet_Main { public static void main(String[] args) { Request request = new Request(); request.str = "hello everyone:),<script>,Welcome to visit mashibing.com ,Everybody is 996 "; Response response = new Response(); response.str = "response"; FilterChain chain = new FilterChain(); chain.add(new HTMLFilter()).add(new SensitiveFilter()); chain.doFilter(request, response); System.out.println(request.str); System.out.println(response.str); } } interface Filter { void doFilter(Request request, Response response, FilterChain chain); } class HTMLFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain chain) { request.str = request.str.replaceAll("<", "[").replaceAll(">", "]") + "HTMLFilter()"; chain.doFilter(request, response); response.str += "--HTMLFilter()"; } } class Request { String str; } class Response { String str; } class SensitiveFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain chain) { request.str = request.str.replaceAll("996", "955") + " SensitiveFilter()"; chain.doFilter(request, response); response.str += "--SensitiveFilter()"; } } class FilterChain { List<Filter> filters = new ArrayList<>(); int index = 0; public FilterChain add(Filter f) { filters.add(f); return this; } public void doFilter(Request request, Response response) { if(index == filters.size()) return; Filter f = filters.get(index); index ++; f.doFilter(request, response, this); } }
result;
- request: HTMLFilter first, then SensitiveFilter
- response: first SensitiveFilter, then HTMLFilter
- Meet demand
servlet filter source code
https://docs.oracle.com/javaee/7/api/toc.htm
Filter
FilterChain
Implementation of Spring MockFilterChain:
- It can be found from the above two codes that the subclass constructs the "link" through a List, and the final call is to traverse the List to realize the "link" transmission.
Summary:
There are two situations in the responsibility chain mode:
-
Pure responsibility chain mode:
A request must be received by a handler object, and a specific handler can only process a request by one of the following two behaviors: processing by himself (assuming responsibility); Put the blame on the next family. -
Impure responsibility chain mode:
It allows a specific handler object to transfer the remaining responsibility to the next home after assuming part of the responsibility of the request, and a request can not be received by any receiving end object.
Applicable scenarios of responsibility chain mode:
The responsibility chain mode mainly decouples the request and processing. Users only need to send the request to the chain without paying attention to the specific content and processing details of the request. The request will be automatically transmitted until a node processes it. It can be applied to the following scenarios:
- Multiple objects can handle the same request, but which object handles it is dynamically determined at run time.
- Submit a request to one of multiple objects without explicitly specifying the recipient
- Processing requests for a set of objects can be dynamically specified.
advantage:
- Reduce coupling. It decouples the sender and receiver of the request.
- Simplifies objects. So that the object does not need to know the structure of the chain.
- Enhance the flexibility of assigning responsibilities to objects. By changing the members in the chain or transferring their order, it is allowed to dynamically add or delete responsibilities.
- It is convenient to add new request processing classes.
Disadvantages:
- If the link of the responsibility chain is too long or the processing time is too long, the performance will be affected.
- If the node object has a circular reference, it will cause an endless loop and cause the system to crash