面向对象的设计:对值对象赋予过多的责任

时间:2013-09-04 20:28:08

标签: java oop

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

  

想象一下,您有一个拥有三个级别员工的呼叫中心:   更新,技术主管(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中收听它们。

2 个答案:

答案 0 :(得分:5)

设计这个系统的方法有很多种(这使得开发软件如此有趣)有些方法比其他方式更好。提供的答案并不是最好的,但它确实有效。

您必须通过对Callhandler进行某些回调来让某个员工通过某种方式升级来电。是通过绕过Callhandler还是Employeecallhandler听取事件来完成这些都是好主意。给定的解决方案更简单,因此更容易理解目标受众。基于事件的解决方案更复杂,更难编写,但更具可扩展性且更易于修改。

例如,如果您必须为某种“监督者”添加新功能,以监控员工成功解决呼叫的频率与他们升级的次数,那么编写新的事件监听器比尝试更容易鞋角是员工和Callhandler之间的新对象。

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

答案 1 :(得分:0)

这就是我设计它的方式。

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

然后基本上更新鲜,TL,PM有不同的等级(“等级”)。

Call Handle可以根据排名将其列为可用人员列表。

EX。如果所有0级员工都不可用+1级别,以查看是否有人可用。

让“较低级别”的员工拥有较高级别并使最高级别排名为1或0甚至更有意义,因此很容易看出结束的位置。