我在《Cracking the Coding Interview》一书中遇到了这个设计问题:
想象一下,您有一个呼叫中心,拥有三个级别的员工:新员工、技术主管 (TL)、产品经理 (PM)。可以有多名员工,但只有一名 TL 或 PM。来电必须分配给空闲的新生。如果应届生无法接听电话,他或她必须将电话上报给技术主管。如果 TL 不是空闲的或无法处理它,那么呼叫应该升级到 PM。为这个问题设计类和数据结构。实现方法 getCallHandler()。
书中的解决方案
public class CallHandler {
static final int LEVELS = 3; // we have 3 levels of employees
static final int NUM_FRESHERS = 5; // we have 5 freshers
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 Call {
int rank = 0; // minimal rank of employee who can handle this call
public void reply(String message) { ... }
public void disconnect() { ... }
}
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
}
}
class Fresher extends Employee {
public Fresher() { super(0); }
}
class TechLead extends Employee {
public TechLead() { super(1); }
}
class ProductManager extends Employee {
public ProductManager() { super(2); }
}
这个解决方案不是很令人满意,主要是因为它涉及将CallHandler
对象传递给Employee
. 我认为Employee
应该被视为一个值对象,这意味着它的工作应该主要是保存数据而不知道包含真实业务逻辑的实体(如CallHandler
)。所以我很想知道有什么更好的方法来设计这个。我来自 ActionScript 背景,因此我可能会使用 ActionScript 的事件模型Employee
从CallHandler
.