需求:
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(); }
}