Definition of a pattern
The responsibility chain pattern is defined as follows:
Avoid coupling the sender of a request to their receiver by giving + than one object a chance to handle the request. Chain the receiving objects and pass the request along the Chain until an object handles it.
Enables multiple objects to have the opportunity to process requests, thus avoiding the coupling between the sender and the recipient of the request. Link the objects together and pass the request along the chain until an object is processed by them.
Type
Behavior Class
Usage Scenarios for patterns
A request can be handled by multiple handlers or the processor does not explicitly refer to timing
Introduction to UML class diagram roles
Handler class-Abstract processor class,
The abstract processing class implements three responsibilities:
One is to define a request processing method Handlermessage, the only way to open the door
The second is to define a chain of compile method Setnext, set the next processor
The third is to define the method that the specific processor must implement: Gethandlerlevel and Echo
Concretehandler Class-specific processor class
Implement several specific processor classes to form a chain that processes messages
The common source of the pattern
Abstract Processor-handler:
Public Abstract classHandler {PrivateHandler Nexthandler;//Set who is the next processor Public void Setnext(Handler Nexthandler) { This. Nexthandler = Nexthandler; }//Get level to process request protected AbstractLevelGethandlerlevel();//Per processor logic for handling request protected AbstractResponseEcho(Request request);//Each processor must process the request PublicFinal ResponseHandlermessage(Request request) {Response Response =NULL;//Determine if you can handle it yourself if(Request.getlevel (). GetId () = = (Gethandlerlevel (). GetId ())) {response = echo (request); System. out. println ("Response:"+response); }Else{//Not the level of your own processing //Determine if there is a next processor if(Nexthandler! =NULL{response = Nexthandler.handlermessage (request); }Else{//response No handlersResponse =NewResponse ("Request does not handle"); System. out. println ("Response:"+response); } }returnResponse }}
The abstract processing class implements three responsibilities:
One is to define a request processing method Handlermessage, the only way to open the door
The second is to define a chain of compile method Setnext, set the next processor
The third is to define the method that the specific processor must implement: Gethandlerlevel and Echo
Specific Processor:
ConcreteHandler1:
Public class ConcreteHandler1 extends Handler { @Override protectedLevelGethandlerlevel() {//TODO auto-generated method stub return NewLevel (1); }@Override protectedResponseEcho(Request request) {//TODO auto-generated method stubSystem.out.println ("ConcreteHandler1----echo:"+request);return NewResponse ("ConcreteHandler1---Echo:"+request); }}
ConcreteHandler2:
Public class ConcreteHandler2 extends Handler { @Override protectedLevelGethandlerlevel() {//TODO auto-generated method stub return NewLevel (2); }@Override protectedResponseEcho(Request request) {//TODO auto-generated method stubSystem.out.println ("ConcreteHandler2----echo:"+request);return NewResponse ("ConcreteHandler2---Echo:"+request); }}
ConcreteHandler3:
Public class ConcreteHandler3 extends Handler { @Override protectedLevelGethandlerlevel() {//TODO auto-generated method stub return NewLevel (3); }@Override protectedResponseEcho(Request request) {//TODO auto-generated method stubSystem.out.println ("ConcreteHandler3----echo:"+request);return NewResponse ("ConcreteHandler3---Echo:"+request); }}
Response class:
Public class Response { protectedString responsestring; Public Response(String responsestring) {Super(); This. responsestring = responsestring; } PublicStringgetresponsestring() {returnresponsestring; } Public void setresponsestring(String responsestring) { This. responsestring = responsestring; }@Override PublicStringtoString() {return "Response [responsestring="+ responsestring +"]"; }}
Level class:
Public class level { protected intId Public Level(intID) {Super(); This. id = ID; } Public int getId() {returnId } Public void setId(intID) { This. id = ID; }@Override PublicStringtoString() {return "level [id="+ ID +"]"; }}
Request class:
Public class Request { protectedString restring;protectedLevel level; Public Request(String restring, level level) {Super(); This. restring = restring; This. level = level; } PublicLevelGetlevel() {returnLevel } Public void SetLevel(level) { This. level = level; } PublicStringgetrestring() {returnrestring; } Public void setrestring(String restring) { This. restring = restring; }@Override PublicStringtoString() {return "Request [restring=]+ restring +", level="+ Level +"]"; }}
Client:
Public classClient { Public Static void Main(string[] args) {//TODO auto-generated method stubRequest Request1 =NewRequest ("request_001",NewLevel (1)); Request Request2 =NewRequest ("request_002",NewLevel (2)); Request Request3 =NewRequest ("request_003",NewLevel (3)); Request Request4 =NewRequest ("request_004",NewLevel (4)); Handler H1 =NewConcreteHandler1 (); Handler H2 =NewConcreteHandler2 (); Handler H3 =NewConcreteHandler3 (); H1.setnext (H2); H2.setnext (H3); Response response1 = H1.handlermessage (Request1); System. out. println ("------------------------------------------------------------------"); Response Response2 = H1.handlermessage (REQUEST2); System. out. println ("------------------------------------------------------------------"); Response response3 = H1.handlermessage (REQUEST3); System. out. println ("------------------------------------------------------------------"); Response Response4 = H1.handlermessage (REQUEST4); }}
Output results
ConcreteHandler1----Echo:Request[Restring=request_001, Level=level [id=1]]Response:Response[Responsestring=concretehandler1---Echo:Request[Restring=request_001, Level=level [id=1]]]------------------------------------------------------------------ConcreteHandler2----echo:Request[Restring=request_002, Level=level [id=2]]Response:Response[Responsestring=concretehandler2---Echo:Request[Restring=request_002, Level=level [id=2]]]------------------------------------------------------------------ConcreteHandler3----echo:Request[Restring=request_003, Level=level [id=3]]Response:Response[Responsestring=concretehandler3---Echo:Request[Restring=request_003, Level=level [id=3]]]------------------------------------------------------------------Response:Response[responsestring=Request Do notHandle
Advantages
Separating requests from processing: The requester can not know who is dealing with, the processor can also not know the requester, the two decoupling, improve the system flexibility.
Disadvantages
One is the performance issue:
Each request is traversed from the chain head to the end of the chain, especially when the chain is longer, performance is a relatively large problem
Second, debugging inconvenient:
Especially when the chain is long, the link is more, using a similar recursive way, debugging logic may be more complex.
Precautions:
The number of nodes in the chain needs to be controlled, to avoid the case of super long chain, the general practice is to set a maximum number of nodes in the handler, in the set Setnext method to determine whether the threshold is exceeded, the chain is not allowed to establish, to avoid the unconscious damage the performance of the system.
Model implementation reference in Android source code
(1). Design pattern of Zen-16th chapter responsibility Chain mode
(2) Responsibility chain mode
https://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/ Chain-of-responsibility/aigestudio
The model of responsibility chain in design mode---pattern chain-of-responsibility