我在"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[] employeeLevels = new ArrayList[LEVELS]; // queues for each call’s rank Queue [] callQueues = new LinkedList[LEVELS]; public CallHandler() { ... } Employee getCallHandler(Call call) { for (int level = call.rank; level < LEVELS - 1; level++) { ArrayList 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
.
设计这个系统有很多方法(这就是使开发软件如此有趣的原因)某些方法比其他方法更好.提供的答案不是最好的,但它有效.
你必须有一些员工的方式通过做一些回调来升级一个电话Callhandler
.无论是通过绕过Callhandler
或有Employee
s和callhandler
听取事件来完成都是好主意.给定的解决方案更简单,因此更容易理解目标受众.基于事件的解决方案更复杂,更难编写,但更具可扩展性且更易于修改.
例如,如果您必须为某种"监督者"添加新功能,以监控员工成功解决呼叫的频率与他们升级的次数,那么只需编写新的事件监听器就可以轻松编写. Employee和Callhandler之间的新对象.
基本上,是的,你的想法可能比解决方案更好,但他们都回答了这个问题.