Cracking the Coding Interview という本の中で、この設計上の質問に出くわしました。
新卒、テクニカル リード (TL)、プロダクト マネージャー (PM) の 3 つのレベルの従業員がいるコール センターがあるとします。複数の従業員を配置できますが、TL または PM は 1 人だけです。電話の着信は、空いている新入社員に割り当てる必要があります。初任者が電話に対応できない場合は、テクニカル リードに電話をエスカレートする必要があります。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
.