Sunday, August 17, 2014

Chain of responsibility Pattern

Chain of responsibility as the name suggests has two parts to it. One is Chain and the other is Responsibility. The chain part is about setting a sequence of things who can process the things. The responsibility part is basically about doing the things.

In any organization, budget approvals are done at different levels based on the hierarchy. Manager can approve till certain amount, but beyond it, it goes to General Manager and so on.Beyond certain amount, even Board or Shareholders (if it is listed) need to involved for the decision making process.

The other important part is setting up the chain. The chain can be set implicitly by participating objects or explicitly by an independent object. For example, in workflow systems, usually the chain is set explicitly based on the process. The systems like leave management system or budget approval systems has implicit chain setting. The boss is set for every individual and based on the condition, the process automatically goes from boss to his/her boss to his/her boss.

Let's build the chain first

public abstract class Employee {
protected Employee boss;

public void setBoss(Employee employee) {
boss = employee;
}

public void applyLeave(int noOfDays) {
Leave leave = new Leave(this, noOfDays);
boss.processLeaveForApproval(leave);

if (leave.isApproved()) {
System.out.println("Pack the fishing gadgets.");
} else {
System.out.println("Open Laptop and start working.");
}
}

abstract public void processLeaveForApproval(Leave leave);
}

public class Developer extends Employee {

@Override
public void processLeaveForApproval(Leave leave) {
// Developer can not process any leave
throw new RuntimeException("Developer cannot process leaves");
}
}

public class Manager extends Employee {

@Override
public void processLeaveForApproval(Leave leave) {
// Make sure one does not approve its own leave
if (leave.getEmployee() == this || leave.getNoOfDays() > 15) {
this.boss.processLeaveForApproval(leave);
} else {
// Manager in good mood, so will approve all leave
System.out.println("Approve by Manager");
leave.setApproved(true);
}
}
}

public class Director extends Employee {

@Override
public void processLeaveForApproval(Leave leave) {
// Director has got stock option recently so in good mood
// Also let's assume he can approve his own leaves also
System.out.println("Approve by Director");
leave.setApproved(true);
}
}

The Leave class for completion

public class Leave {

int noOfDays;
boolean approved = false;
Employee employee;

public Leave(Employee employeeApplied, int days) {
employee = employeeApplied;
noOfDays = days;
}

public void setApproved(boolean approved) {
this.approved = approved;
}

public boolean isApproved() {
return approved;
}

public Employee getEmployee() {
return employee;
}

public int getNoOfDays() {
return noOfDays;
}

}

And now the usage

public class ChainOfResponsibility {

public static void main(String[] args) {
Director director = new Director();
director.setBoss(director);

Manager manager = new Manager();
manager.setBoss(director);

Developer developer1 = new Developer();
developer1.setBoss(manager);
Developer developer2 = new Developer();
developer2.setBoss(manager);

developer1.applyLeave(10);
developer2.applyLeave(20);
manager.applyLeave(5);
director.applyLeave(1);
}

No comments:

Post a Comment