我在《破解编码面试》一书中遇到了这个设计问题:
假设您有一个呼叫中心,该呼叫中心有三级员工:
新生,技术负责人(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
还是让Employee
和callhandler
监听事件都是好主意。给定的解决方案更简单,因此目标受众更容易理解。基于事件的解决方案更加复杂,更难编写,但可扩展性更高,更易于修改。
例如,如果您必须为某种“监督者”添加一项新功能,以监视员工成功解决呼叫的频率及其上报的次数,那么编写一个新的事件侦听器而不是尝试耗费大量精力就容易了。 Employee和Callhandler之间的新对象。
基本上,是的,您的想法可能比解决方案更好,但是它们都回答了问题。
关于java - 面向对象的设计:对值(value)对象负太多责任,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18623180/