我在《破解编码面试》一书中遇到了这个设计问题:


  假设您有一个呼叫中心,该呼叫中心有三级员工:
  新生,技术负责人(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中收听它们。

最佳答案

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

您必须具有某种Employee方式,通过对Callhandler进行某种回调来升级呼叫。无论是通过绕过Callhandler还是让Employeecallhandler监听事件都是好主意。给定的解决方案更简单,因此目标受众更容易理解。基于事件的解决方案更加复杂,更难编写,但可扩展性更高,更易于修改。

例如,如果您必须为某种“监督者”添加一项新功能,以监视员工成功解决呼叫的频率及其上报的次数,那么编写一个新的事件侦听器而不是尝试耗费大量精力就容易了。 Employee和Callhandler之间的新对象。

基本上,是的,您的想法可能比解决方案更好,但是它们都回答了问题。

关于java - 面向对象的设计:对值(value)对象负太多责任,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18623180/

10-09 13:40