The Chain of Responsibility pattern. Java implementation example
This topic provides an example of the implementation of the Chain of Responsibility pattern in Java for a structure containing a hierarchy of handler classes. Before exploring the topic, it is recommended that you familiarize yourself with the general information about the Chain of Responsibility pattern, which is described in the topic:
Contents
- 1. Task
- 2. The solution of task
- 2.1. Creating the ChainMethod() method
- 2.2. Building the structure of classes that implement the Chain of Responsibility pattern. Figure
- 2.3. The Handler class
- 2.4. The Handlers1 class
- 2.5. Handler classes ConcreteHandler1, ConcreteHandler2
- 2.6. The handler class ConcreteHandler3
- 2.7. The handler class ConcreteHandler4. End of the chain
- 2.8. Testing the work of the handler classes. Function main(). Dispatching
- 2.9. Abbreviated program structure
- Related topics
Search other resources:
1. Task
Let 4 classes ConcreteHandler1, ConcreteHandler2, ConcreteHandler3, ConcreteHandler4 be given. The two classes ConcreteHandler1, ConcreteHandler2 inherit from the Handlers1 class, as shown in Figure 1.
Figure 1. The hierarchy of ConcreteHandler1, ConcreteHandler2, Handlers1 classes
It is necessary to develop a Java application in which the above classes handle a single request from the client and are organized in a chain based on the Chain of Responsibility pattern. Demonstrate how the handler classes work by implementing dispatching.
⇑
2. The solution of task
2.1. Creating the ChainMethod() method
First of all, the ChainMethod() method is introduced into each class, which is the handler itself. This means that this method is processing the client’s request. In our case, the method will display messages about the class name and method name. For example, for the ConcreteHandler1 class, the method will display the message
ConcreteHandler1.ChainMethod
The ChainMethod() method will be passed along the chain to be processed by one of the handler classes.
⇑
2.2. Building the structure of classes that implement the Chain of Responsibility pattern. Figure
Based on the general structure of the Chain of Responsibility pattern and the input of the ChainMethod() method, the structure shown in Figure 2 is developed.
Figure 2. The structure of the Chain of Responsibility pattern for the classes implemented in the current example
The following steps develop the classes shown in Figure 1.
⇑
2.3. The Handler class
The base class in the hierarchy is the Handler class. This class creates all the functionality required to implement the Chain of Responsibility pattern. The class declares:
- internal field successor, which is a reference to the successor. This reference is used in every handler class ConcreteHandler1, ConcreteHandler2, ConcreteHandler3. In the ConcreteHandler4 class, this reference is set to null because this class is the last in the chain of handlers;
- internal field numHandler, which is the handler number. Based on this number, the DoRequest() method determines whether the request can be handled by a handler;
- three constructors designed to create an instance of the handler class based on specifying (not specifying) data about the successor and the handler number (numHandler);
- the ChainMethod() method. This method handles the request directly;
- the DoRequest() method, which, based on the value of numHandler, determines whether to process the request. If numHandler is -1, then the request is not processed;
- the SetHandler() method – implements the installation of a handler (successor) and its number (numHandler) after an instance of one of the handler classes is created.
The text of the Handler class is as follows.
// A class that is the only interface for objects that process a request. // The class contains methods that are common to handle. class Handler { // 1. Internal variables // 1.1. Successor reference private Handler successor = null; // 1.2. Number of the handler processing the request private int numHandler = -1; // 2. Constructor // 2.1. Constructor without a parameters public Handler() { this(null, -1); } // 2.2. Constructor with 1 parameter public Handler(Handler _successor) { this(_successor, -1); } // 2.3. Constructor with 2 parameters public Handler(Handler _successor, int _numHandler) { successor = _successor; numHandler = _numHandler; } // A method that moves along a chain. // This method processes the request. public void ChainMethod() { if (successor!=null) successor.ChainMethod(); } // A method that determines whether the request should be processed. public boolean DoRequest() { return numHandler != -1; } // Method that sets the handler and the ability to handle public void SetHandler(Handler _successor, int _numHandler) { successor = _successor; numHandler = _numHandler; } }
⇑
2.4. The Handlers1 class
The Handlers1 class is a superclass for the ConcreteHandler1 and ConcreteHandler2 handler classes. For the correct implementation of the Chain of Responsibility pattern, this class must inherit from the Handler class. In the context of our task, the class contains a constructor that calls the constructor of the Handler superclass.
Depending on the problem being solved, besides the constructor, this class may contain other methods and fields.
The Java text for the Handlers1 class is as follows.
// Intermediate class that is the base for specific handlers // ConcreteHandler1, ConcreteHandler2 class Handlers1 extends Handler { // Class constructor public Handlers1(Handler _parent, int _numHandler) { // Call the base class constructor super(_parent, _numHandler); } }
⇑
2.5. Handler classes ConcreteHandler1, ConcreteHandler2
The classes-handlers ConcreteHandler1, ConcreteHandler2 are inherited from the Handlers1 class. Therefore, the constructors of these classes redirect the inheritor to the constructor of the Handlers1 class. The classes also contain the ChainMethod() method that implements processing.
Additionally, these classes can contain other components that will determine their purpose. The text of the ConcreteHandler1 and ConcreteHandler2 classes is given below.
// Concrete handler - 1 class ConcreteHandler1 extends Handlers1 { // Constructor - calls the constructor of the base class Handlers1 public ConcreteHandler1(Handler _parent, int _numHandler) { // Call the constructor of the superclass super(_parent, _numHandler); } // Specific processing method public void ChainMethod() { // Checking if a handler is processing a given request if (super.DoRequest()) { // If it does, then take the appropriate action. System.out.println("ConcreteHandler1.ChainMethod"); } else { super.ChainMethod(); } } } // Concrete handler - 2 class ConcreteHandler2 extends Handlers1 { public ConcreteHandler2(Handler _parent, int _numHandler) { // Call the superclass constructor super(_parent, _numHandler); } // Specific processing method public void ChainMethod() { // Checking if a handler is processing a given request if (super.DoRequest()) { // If it does, then take the appropriate action. System.out.println("ConcreteHandler2.ChainMethod"); } else { super.ChainMethod(); } } }
⇑
2.6. The handler class ConcreteHandler3
The ConcreteHandler3 handler class inherits from the base Handler class. This class is not the final link in the call chain.
The class program code is as follows.
// Concrete handler - 3 // This handler is not part of the class hierarchy // in which the Handlers1 class is the base class. class ConcreteHandler3 extends Handler { // Constructor public ConcreteHandler3(Handler _handler, int _numHandler) { // Call the superclass constructor super(_handler, _numHandler); } // Specific processing method public void ChainMethod() { // Checking if a handler is processing a given request if (super.DoRequest()) { // If it does, then take the appropriate action. System.out.println("ConcreteHandler3.ChainMethod"); } else { super.ChainMethod(); } } }
⇑
2.7. The handler class ConcreteHandler4. End of the chain
The ConcreteHandler4 handler class is the last in the chain of calls. Processing in the ChainMethod() method is done accordingly.
The class text is as follows.
// Concrete handler - 4 // This handler is not part of a class hierarchy where // base class is Handlers1. // This handler is the last in the chain of handlers. class ConcreteHandler4 extends Handler { // Constructor. // Since the handler is the last in the chain of handlers, // it does not need to pass a reference to the previous handler. public ConcreteHandler4(int _numHandler) { super(null, _numHandler); } // Specific processing method public void ChainMethod() { // Checking if a handler is processing a given request if (super.DoRequest()) { // If it does, then take the appropriate action. System.out.println("ConcreteHandler4.ChainMethod"); } else { // If the handler does not process this request, // then display a message stating that // there is no corresponding handler in the chain. System.out.println("There is no corresponding handler in the chain."); } } }
⇑
2.8. Testing the work of the handler classes. Function main(). Dispatching
In this example, the client is the TrainChain class, which contains the main() function – the entry point into the program. In the main() function, the following actions are performed:
- a chain of handlers is created based on the handler classes described above;
- a client object is created, pointing to the chain of handler objects;
- installation and invocation of the appropriate handler based on the simplified dispatch code is demonstrated.
To enter data from the keyboard, the capabilities of the Scanner class are used, which is connected using the directive
import java.util.Scanner;
The client code text is as follows
// Include the Scanner module import java.util.Scanner; ... // The client class public class TrainChain { public static void main(String[] args) { // Client code. // 1. Create a chain of 4 handlers. // Handlers are created in order from last to first. // 1.1. The last handler in the chain is created first. ConcreteHandler4 handler4 = new ConcreteHandler4(4); // 4 - handler number // 1.2. Add next handler. // The handler receives a reference to the previous handler handler4 ConcreteHandler3 handler3 = new ConcreteHandler3((Handler)handler4, 3); // 1.3. Add handlers that are subclasses of the Handlers1 class // 1.3.1. The handler that follows the second in the chain. ConcreteHandler2 handler2 = new ConcreteHandler2((Handler)handler3, 2); // 1.3.2. The first handler in the chain. ConcreteHandler1 handler1 = new ConcreteHandler1((Handler)handler2, 1); // 2. Create a client. // Client points to a chain of handler objects // client -> handler1 -> handler2 -> handler3 -> handler4 Handler client = new Handler((Handler)handler1); // 3. Enter the handler number from the keyboard System.out.println("numHandler = "); Scanner input = new Scanner(System.in); int numHandler = input.nextInt(); // 4. Depending on numObject implement dispatching switch (numHandler) { case 1: // Set handler-1 for client and call it client.SetHandler(handler1, 1); client.ChainMethod(); break; case 2: // Set handler-2 for client and call it client.SetHandler(handler2, 2); client.ChainMethod(); break; case 3: // Set handler-3 for client and call it client.SetHandler(handler3, 3); client.ChainMethod(); break; case 4: // Set handler-4 for client and call it client.SetHandler(handler4, 4); client.ChainMethod(); break; default: System.out.println("Incorrect handler"); break; } // Close the input stream input.close(); } }
⇑
2.9. Abbreviated program structure
To get the entire program code, you need to copy the program codes presented in paragraphs 2.1-2.5 of this topic. In an abbreviated form, the structure of the program is as follows:
// Include the Scanner module import java.util.Scanner; // A class that is the only interface for objects that process a request class Handler { ... } // Intermediate class that is the base for specific handlers // ConcreteHandler1, ConcreteHandler2 class Handlers1 extends Handler { ... } // Concrete handler - 1 class ConcreteHandler1 extends Handlers1 { ... } // Concrete handler - 2 class ConcreteHandler2 extends Handlers1 { ... } // Concrete handler - 3 class ConcreteHandler3 extends Handler { ... } // Concrete handler - 4 class ConcreteHandler4 extends Handler { ... } // Client class public class TrainChain { public static void main(String[] args) { ... } }
⇑
Related topics
- The Chain of Responsibility pattern. General information. Implementation in C++
- Chain of Responsibility pattern. An example of implementation in C# for a given class structure
⇑