How to implement Chain of Responsibility pattern in Java?

Photo by Luděk Maděryč on Pexels.com

Let’s say you run a hospital.

And you are developing an application to handle patients.

You have created a process:

All patients are first attend by a junior doctor.

The junior doctor checks the symptoms and if the severity is low , she treats them , else she sends the patient to the senior doctor.

The senior doctor then checks the patient and if he finds that the severity is high he treats them , else if it is critical he sends them to the Chief Doctor.

The Chief doctor treats only critical cases.

I am making simplistic assumptions here . If a patients has met with an accident you cannot afford to follow this process strictly. Those scenarios are discarded here.

Now let’s see how the Chain of Responsibility pattern helps in implementing this.

The Chain of Responsibility patterns decouples a request from the receiver who is going to handle the request . The request passes through a chain of receivers who decide whether they can handle the request or not and if not passes them to the next receiver in the chain.

Let’s look at our client code first:

package behavioural.chainofresponsibility.pattern;

public class Client {
	
	
	public static void main(String a[]) {
		
		
		ChiefDoctor chiefDoctor = new ChiefDoctor();
		SeniorDoctor seniorDoctor = new SeniorDoctor(chiefDoctor);
		JuniorDoctor juniorDoctor = new JuniorDoctor(seniorDoctor);
		
		
		System.out.println("---------Patient Kumar------------");
		
		juniorDoctor.checkPatient("Kumar", "severe bodyache");
		
		System.out.println("---------Patient Raghav------------");
		juniorDoctor.checkPatient("Raghav", "cold");
		
		System.out.println("---------Patient Varun------------");
		
		juniorDoctor.checkPatient("Varun", "fracture");
		
		
		
		
	}

}

We are first creating objects for each doctor in the hierarchy. A Chief Doctor , a Senior Doctor and a Junior Doctor. The supervisor / successor of each doctor is passed as a constructor argument.

Eg) Since the sucessor of a junior doctor is a senior doctor , the senior doctor instance is passed as a parameter to the constructor of the junior doctor.

Any patient is first attended by the Junior Doctor. And so all the patients in the above code: Kumar, Raghav and Arun are first checked by the junior doctor. But as you can see later they are finally treated by different doctors based on the severity of their condition.

All the doctors belong to the same interface:

package behavioural.chainofresponsibility.pattern;

public interface Doctor {

	public abstract void checkPatient(String name,String symptoms);
	
	public abstract String checkSeverity(String symptoms);
}

checkPatient() method checks a patient and based on their severity either treats the patient or passes them to their successor .The severity of the patient is calculated by the checkSeverity() method.

Here is the Junior Doctor class:

package behavioural.chainofresponsibility.pattern;

public class JuniorDoctor implements Doctor {

	private Doctor successor;

	public JuniorDoctor(Doctor doctor) {

		this.successor = doctor;
	}

	@Override
	public void checkPatient(String name, String symptoms) {

		String severity = checkSeverity(symptoms);

		if (severity.equals("low")) {

			System.out.println("Patient treated by Junior Doctor");
		} else {
			System.out.println("Severity not low -> directing it to next doctor");

			this.successor.checkPatient(name, symptoms);
		}

	}

	public String checkSeverity(String symptoms) {

		System.out.println("Patient being checked by Junior Doctor");

		if (symptoms.contains("fever") || symptoms.contains("cough") || symptoms.contains("cold")) {

			return "low";
		} else {
			return "high";
		}
	}

}

The constructor of the Junior Doctor is passed a Doctor instance. This can be set dynamically in the client code. This is a major feature of the Chain of Responsibility pattern. The client code can decide which doctor should the Junior Doctor forward the patient to , if she cannot treat them.

As you can see in the checkPatient() method , if the severity is low the junior doctor treats them else she passes the patient to the next doctor which is set as the Senior Doctor in the client code.

Here is the Senior Doctor class:

package behavioural.chainofresponsibility.pattern;

public class SeniorDoctor implements Doctor {
	
	private Doctor successor;
	
	public SeniorDoctor(Doctor doctor) {
		
		this.successor = doctor;
	}

	@Override
	public void checkPatient(String name,String symptoms) {
		
		String severity = checkSeverity(symptoms);
		
		
		if(severity.contentEquals("high")) {
			
			
			System.out.println("Patient treated by Senior Doctor ");
		}else {
			
			System.out.println("Severity more than high -> directing it to next doctor");
			
			this.successor.checkPatient(name,symptoms);
		}
		
		

	}

	@Override
	public String checkSeverity(String symptoms) {
		System.out.println("Patient being checked by Senior Doctor");
		
		if(symptoms.equals("breathing difficulty")|| symptoms.contentEquals("severe bodyache")) {
			
			return "high";
		}else {
		return "critical";
		}
	}

}

The Senior Doctor does the same but he treats patients only with high severity .Else he forwards to the next doctor in the chain which is set as Chief Doctor in the client code.

Here is the Chief Doctor class:

package behavioural.chainofresponsibility.pattern;

public class ChiefDoctor implements Doctor {

	private Doctor successor;

	public ChiefDoctor() {
		
		
	}
	public ChiefDoctor(Doctor doctor) {

		this.successor = doctor;
	}

	@Override
	public void checkPatient(String name, String symptoms) {

		String severity = checkSeverity(symptoms);

		if (severity.equals("critical")) {

			System.out.println("Chief Doctor treating patient :" + name);
			System.out.println("Patient condition is critical");
		} else {

			System.out.println("No doctor available to treat patient for the given symptoms");
		}

	}

	@Override
	public String checkSeverity(String symptoms) {

		System.out.println("Patient being checked by Chief Doctor");

		if (symptoms.equals("rapid heart beat") || symptoms.equals("fracture")) {
			return "critical";
		} else {

			return "uncategorized";
		}
	}

}

Chief Doctor is similar to Senior Doctor code except that :

  1. Chief doctor only handles critical cases.
  2. I have included a no-arg constructor as there is no successor to the Chief Doctor. But it can be added at run time by using the other constructor with a ‘Doctor’ parameter.

Here is the output of the client code :

---------Patient Kumar------------
Patient being checked by Junior Doctor
Severity not low -> directing it to next doctor
Patient being checked by Senior Doctor
Patient treated by Senior Doctor 
---------Patient Raghav------------
Patient being checked by Junior Doctor
Patient treated by Junior Doctor
---------Patient Varun------------
Patient being checked by Junior Doctor
Severity not low -> directing it to next doctor
Patient being checked by Senior Doctor
Severity more than high -> directing it to next doctor
Patient being checked by Chief Doctor
Chief Doctor treating patient :Varun
Patient condition is critical

That’s it.

Quoting the Gang of Four :

Avoid coupling the sender of a request to its receiver by giving more 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.

And they suggest to use it when :

– more than one object may handle a request and the handles isn’t know a priori. The handler should be ascertained automatically (in our case , a patient can be handled by any of the three doctors and the patient doesn’t know which doctor is going to treat him)

– you want to issue a request to one of several objects without specifying the receiver explicitly.( we don’t specify explicitly which doctor is going to handle the patient)

– the set of objects that can handle a request should be specified dynamically ( the doctors in the chain of handlers can be set dynamically in the client code by passing different values for the constructors)

Here is the code :

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/behavioural/chainofresponsibility/pattern

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s