2

我在《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 的事件模型EmployeeCallHandler.

4

2 回答 2

6

有无数种方法可以设计这个系统(这就是开发软件如此有趣的原因),有些方法比其他方法更好。提供的答案不是最好的,但它有效。

You have to have some way of an Employee to escalate a call by doing somekind of callback to the Callhandler. Whether that is done by passing around the Callhandler or having Employees and callhandlers listening to events are both good ideas. The given solution is simpler and therefore more easy to understand for the target audience. An event based solution is more complicated, harder to write but more scalable and easier to modify.

For example, if you had to add a new feature for some kind of "overseer" to monitor how often Employees successfully resolve calls versus how many times they escalate, it would be easy to just write a new event listener than try to shoe-horn a new object between the Employee and the Callhandler.

Basically, yes your ideas are probably better than the solution, but they both answer the question.

于 2013-09-04T20:45:57.453 回答
0

This is how I would design it.

Employee as an interface
    properties->
        int rank = 0;
        bool availability;
    branches off to(these classes extend employee) ->
        fresher
        TL
        PM

Then essentially fresher, TL, PM have different ranks("levels").

Call Handle can base it off a list of who's available based on rank.

EX. If all rank 0 employees are not available +1 the level to see if anyone up there is available.

It might even make more sense to have "lower level" employees have higher levels and make the top dog rank 1 or 0 so it'll be simple to see where the end is.

于 2013-09-04T21:03:00.073 回答