需求:
1、銀行內有6個服務視窗:4個普通客戶視窗、1個VIP客戶視窗、1個快速視窗
2、3種客戶:普通客戶、VIP客戶視窗、快速視窗
3、
先類比下這個業務:
服務視窗開始叫號
4個普通客戶視窗開始服務;
1個VIP客戶視窗開始服務;
1個快速視窗開始服務;
客戶進來辦理業務取號
普通客戶取號等待被叫,
VIP客戶取號等待被叫,
快速客戶取號等待被叫,
從這瞭解到服務人員是通過各自的視窗向號碼管理器要相應的號碼,客戶是選擇相應的號碼產生器取號等待被叫。
現在我們抽象下業務上的資料:服務視窗(不同的視窗向不同的取號器取號),服務視窗包括銀行服務視窗和客戶取號視窗;要取號就需要有號碼管理器;而客戶和服務人員都是向不同的號碼管理器取號,這裡是否需要一個管理各種號碼管理器的類。客戶有3種類型。
我們分別設計這幾個類。
1、服務視窗的設計(包括2種)
面向銀行服務人員的:
public class ServerWindow implements Runnable{
private CustomerType type;
private int windowNum;
public void setType(CustomerType type) {
this.type = type;
}
public void setWindowNum(int windowNum) {
this.windowNum = windowNum;
}
@Override
public void run() {
while(true){
switch(type){
case COMMON:
commonService();
break;
case EXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
/**
* 普通視窗
*/
private void commonService(){
String windowName = "第" + windowNum + "號" + type + "視窗";
Integer serverNum = NumMachine.getInstance().getCommManager().serverWindowFetchNum();
if(serverNum != null){
int maxServerTime = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
int serverTime = new Random().nextInt(maxServerTime)+1 + Constants.MIN_SERVICE_TIME;
try {
System.out.println(windowName + "開始為第" + serverNum + "號普通客戶服務");
Thread.sleep(serverTime);
System.out.println(windowName + "完成為第" + serverNum + "號普通客戶服務,總共耗時" + serverTime/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
try {
System.out.println(windowName + "沒有取到普通任務,正在空閑一秒");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 快速視窗
*/
private void expressService(){
String windowName = "第" + windowNum + "號" + type + "視窗";
Integer serverNum = NumMachine.getInstance().getExpManager().serverWindowFetchNum();
if(serverNum != null){
int serverTime = Constants.MIN_SERVICE_TIME;
try {
System.out.println(windowName + "開始為第" + serverNum + "號快速客戶服務");
Thread.sleep(serverTime);
System.out.println(windowName + "完成為第" + serverNum + "號快速客戶服務,總共耗時" + serverTime/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println(windowName + "沒有取到快速任務。");
commonService();
}
}
/**
* VIP視窗
*/
private void vipService(){
String windowName = "第" + windowNum + "號" + type + "視窗";
Integer serverNum = NumMachine.getInstance().getVipManager().serverWindowFetchNum();
if(serverNum != null){
int maxServerTime = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
int serverTime = new Random().nextInt(maxServerTime)+1 + Constants.MIN_SERVICE_TIME;
try {
System.out.println(windowName + "開始為第" + serverNum + "號VIP客戶服務");
Thread.sleep(serverTime);
System.out.println(windowName + "完成為第" + serverNum + "號VIP客戶服務,總共耗時" + serverTime/1000 + "秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
System.out.println(windowName + "沒有取到VIP任務。");
commonService();
}
}
}
面向客戶人員的:
public class CustomerFetchMachine {
public static void commFetchNum() {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer serviceNumber = NumMachine.getInstance().getCommManager().clientFetchNum();
System.out.println("第" + serviceNumber + "號普通客戶正在等待服務。");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
}
public static void vipFetchNum() {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer serviceNumber = NumMachine.getInstance().getVipManager().clientFetchNum();
System.out.println("第" + serviceNumber + "號VIP客戶正在等待服務。");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
TimeUnit.SECONDS);
}
public static void expFetchNum() {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
Integer serviceNumber = NumMachine.getInstance().getExpManager().clientFetchNum();
System.out.println("第" + serviceNumber + "號快速客戶正在等待服務。");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,
TimeUnit.SECONDS);
}
}
2、號碼管理的設計
用來管理單個視窗的號碼:
public class NumManager {
private int num = 0;
private List queueNums = new ArrayList();
public synchronized Integer clientFetchNum(){
queueNums.add(++num);
return num;
}
public synchronized Integer serverWindowFetchNum(){
if(queueNums.size() > 0){
return (Integer) queueNums.remove(0);
}
return null;
}
}
用來管理所有視窗的號碼:
public class NumMachine {
private static NumMachine instance = new NumMachine();
private NumManager commManager = new NumManager();
private NumManager expManager = new NumManager();
private NumManager vipManager = new NumManager();
private NumMachine(){}
public NumManager getCommManager() {
return commManager;
}
public NumManager getExpManager() {
return expManager;
}
public NumManager getVipManager() {
return vipManager;
}
public static NumMachine getInstance(){
return instance;
}
}
寫個測試類別類比:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//產生4個普通視窗
for(int i=1;i<5;i++){
ServerWindow win = new ServerWindow();
win.setType(CustomerType.COMMON);
win.setWindowNum(i);
new Thread(win).start();
}
//產生1個vip視窗
ServerWindow vipWin = new ServerWindow();
vipWin.setType(CustomerType.VIP);
vipWin.setWindowNum(6);
new Thread(vipWin).start();
//產生1個快速視窗
ServerWindow expWin = new ServerWindow();
expWin.setType(CustomerType.EXPRESS);
expWin.setWindowNum(5);
new Thread(expWin).start();
//類比使用者取號:普通客戶、vip客戶、快速客戶
CustomerFetchMachine.commFetchNum();
CustomerFetchMachine.vipFetchNum();
CustomerFetchMachine.expFetchNum();
}
}