Problem

Imagine you have a call center with three levels of employees: fresher, technical lead (TL), product manager (PM). There can be multiple employees, but only one TL or PM. An incoming telephone call must be allocated to a fresher who is free. If a fresher can’t handle the call, he or she must escalate the call to technical lead. If the TL is not free or not able to handle it, then the call should be escalated to PM. Design the classes and data structures for this problem. Implement a method getCallHandler().

Solution

All three ranks of employees have different work to be done, so those specific functions are profile specific. We should keep these specific things within their respective class.

There are a few things which are common to them, like address, name, job title, age, etc. These things can be kept in one class and can be extended / inherited by others.

Finally, there should be one CallHandler class which would route the calls to the concerned person.

NOTE: On any object oriented design question, there are many ways to design the objects. Discuss the trade-offs of different solutions with your interviewer. You should usually design for long term code flexibility and maintenance.

CallHandler class:

  1. stores all employees in different levels
  2. stores all calls in a Queue.
  3. getCallHandler() returns a Employee who is suitable for accepting this call.
  4. dispatchCall() gets a employeer from 3, then try ReceiveCall(), if return from 3 is null, put call in Queue.

Call class:

  1. call have ranks.
  2. call can be reply and disconnected.

Main classes

Employee class

  1. Every Employee have a CallHandler
  2. every Employee have a rank.
  3. ReceiveCall()
  4. CallHandled()
  5. CannotHandle(), if can’t handle, handlerObj.dispatchCall(call) and handlerObj.getNextCall()
  6. boolean free. is free or not.

We can define abstract class:

class Employee {
	CallHandler callHandler;
	int rank; // 0- fresher, 1 - technical lead, 2 - product manager
	boolean free;
	Employee(int rank) {
		this.rank = rank;
	}

	void ReceiveCall(Call call) { ...
	}

	void CallHandled(Call call) { ...
	} // call is complete
	void CannotHandle(Call call) { // escalate call
		call.rank = rank + 1;
		callHandler.dispatchCall(call);
		free = true;
		callHandler.getNextCall(this); // look for waiting call
	}
}
Extensions of Employee
class Fresher extends Employee {

	public Fresher() {
		super(0);
	}
}
class TechLead extends Employee {

	public TechLead() {
		super(1);
	}
}
class ProductManager extends Employee {

	public ProductManager() {
		super(2);
	}
}

Call Class

class Call {
	int rank = 0; // minimal rank of employee who can handle this call
	public void reply(String message) { ...
	}

	public void disconnect() { ...
	}
}

CallHandler Class

public class CallHandler {
	static final int LEVELS = 3; // we have 3 levels of employees
	static final int NUM_FRESHERS = 5; // we have 5 freshers no vars needed for TL and PM cuz only 1.
	ArrayList<Employee> [] employeeLevels = new ArrayList[LEVELS];
	// queues for each call’s rank
	Queue<Call> [] callQueues = new LinkedList[LEVELS];

	public CallHandler() { ...
	}

	Employee getCallHandler(Call call) {
		for (int level = call.rank; level < LEVELS - 1; level++) {
			ArrayList<Employee> employeeLevel = employeeLevels[level];

			for (Employee emp: employeeLevel) {
				if (emp.free) {
					return emp;
				}
			}
		}

		return null;
	}

	// routes the call to an available employee, or adds to a queue
	void dispatchCall(Call call) {
		// try to route the call to an employee with minimal rank
		Employee emp = getCallHandler(call);

		if (emp != null) {
			emp.ReceiveCall(call);
		} else {
			// place the call into queue according to its rank
			callQueues[call.rank].add(call);
		}
	}

	void getNextCall(Employee e) { ...
	} // look for call for e’s rank
}

Class Diagram

classDiagram
	class CallHandler {
		+ static int LEVELS
		+ static int NUM_FRESHERS
		- ArrayList~Employee~[] employeeLevels
		- Queue~Call~[] callQueues
		+ CallHandler()
		+ Employee getCallHandler(Call call)
		+ void dispatchCall(Call call)
		+ void getNextCall(Employee e)
	}
	
	class Employee {
		- CallHandler callHandler
		- int rank
		- boolean free
		+ Employee(int rank)
		+ void ReceiveCall(Call call)
		+ void CallHandled(Call call)
		+ void CannotHandle(Call call)
	}
	
	class Call {
		- int rank
		+ void reply(String message)
		+ void disconnect()
	}
	
	CallHandler o--> Employee : manages
	CallHandler o--> Call : manages
	Employee --> CallHandler : uses
	Employee <|-- Fresher
	Employee <|-- TechLead
	Employee <|-- ProductManager
	Call o--> Employee : handled by
  

You can download the detailed code here on github, but this is the code in java: