Java 面向对象设计:赋予价值对象太多的责任
我在《破解编码采访》一书中遇到了这个设计问题: 假设您有一个呼叫中心,有三个级别的员工: 新员工、技术负责人(TL)、产品经理(PM)。可能有 多名员工,但只有一名TL或PM。来电 必须分配给免费的新生。如果一个新生不能处理 电话,他或她必须将电话上报给技术负责人。如果 TL没有空闲或无法处理它,那么调用应该是 升级到PM。为此设计类和数据结构 问题实现一个getCallHandler()方法 书中的解决方案Java 面向对象设计:赋予价值对象太多的责任,java,oop,Java,Oop,我在《破解编码采访》一书中遇到了这个设计问题: 假设您有一个呼叫中心,有三个级别的员工: 新员工、技术负责人(TL)、产品经理(PM)。可能有 多名员工,但只有一名TL或PM。来电 必须分配给免费的新生。如果一个新生不能处理 电话,他或她必须将电话上报给技术负责人。如果 TL没有空闲或无法处理它,那么调用应该是 升级到PM。为此设计类和数据结构 问题实现一个getCallHandler()方法 书中的解决方案 public class CallHandler { static final
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); }
}
公共类调用处理程序{
静态final int LEVELS=3;//我们有3个级别的员工
静态final int NUM_freashers=5;//我们有5个freashers
ArrayList[]employeeLevels=新ArrayList[LEVELS];
//为每个呼叫的级别排队
Queue[]callQueues=新链接列表[级别];
公共调用处理程序(){…}
员工getCallHandler(调用){
对于(int-level=call.rank;level
这个解决方案不是很令人满意,主要是因为它涉及将
CallHandler
对象传递给Employee
。我认为Employee
应该被视为一个值对象,这意味着它的工作应该主要是保存数据,而不知道包含真正业务逻辑的实体(比如CallHandler
)。所以我很想找出更好的设计方法。我来自ActionScript的背景,我可能会使用ActionScript的事件模型从员工
发送消息,并在CallHandler
中聆听它们。设计这个系统的方法有无数种(这就是为什么开发软件如此有趣的原因)。有些方法比其他方法更好。提供的答案不是最好的,但很有效
您必须让员工通过某种方式将呼叫升级到Callhandler
。无论是通过传递Callhandler
还是让Employee
s和Callhandler
s收听事件来实现这一点都是好主意。给定的解决方案更简单,因此目标受众更容易理解。基于事件的解决方案更复杂,更难编写,但更具可扩展性,更易于修改
例如,如果您必须为某种“监管者”添加一个新功能,以监控员工成功解决呼叫的频率与他们升级的次数,那么只编写一个新的事件侦听器比尝试在员工和呼叫处理程序之间创建一个新对象要容易得多
基本上,是的,您的想法可能比解决方案更好,但它们都回答了问题。我将这样设计它
Employee as an interface
properties->
int rank = 0;
bool availability;
branches off to(these classes extend employee) ->
fresher
TL
PM
然后本质上更新鲜,TL、PM有不同的等级(“级别”)
呼叫手柄可以根据级别列出可用的人员
例如,如果所有0级员工都不可用+1,则该级别将查看是否有人可用
让“低级别”的员工拥有更高的级别,并让顶级员工排名1或0,这可能更有意义,因此很容易看出最终结果 这是一个骗人的问题;没有一个PM会处理一个普通的支持电话。@DaveNewton你能再解释一下吗?它在哪里向员工传递
CallHandler
?我所看到的只是把一个电话
传给一名员工。CallHandler找到了一个员工来处理这个电话。CallHandler听起来像是一个单身汉,也许关于这本书的更多信息可以帮助我们。是给初学者的吗?