需求:
銀行內有6個業務視窗,1 - 4號視窗為普通視窗,5號視窗為快速視窗,6號視窗為VIP視窗。
有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。
非同步隨機產生各種類型的客戶,產生各類型使用者的機率比例為:VIP客戶 :普通客戶 :快速客戶 = 1 :6 :3。
客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,快速客戶辦理業務所需時間為最小值(提示:辦理業務的過程可通過線程Sleep的方式類比)。
各類型客戶在其對應視窗按順序依次辦理業務。
當VIP(6號)視窗和快速業務(5號)視窗沒有客戶等待辦理業務的時候,這兩個視窗可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。
隨機產生客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設定。
不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程式運行結果。
商務程序與分析:
流程:現在的銀行資訊化程度都很高,每當我們去銀行辦理業務時,都是要先取號,在排隊等候叫號,並且會區分各種的特殊類型,先取號的先辦業務,遵循著這樣的流程,但是我們知道辦理業務的人有很多種分類,有大額交易、理財服務的,還有轉賬匯款結算的業務、還有各種繳費業務等。有的也叫做公司業務、個人業務、貴賓(VIP)業務、等等。我們按照項目的需求來做,本需求中有三類客戶人群,VIP客戶,普通客戶,快速客戶。有6個服務視窗:1 - 4號視窗為普通視窗,5號視窗為快速視窗,6號視窗為VIP視窗。但是服務的視窗要給客戶服務,需要的唯一憑證是你已經取號,所以有一個號碼機器,並且這個機器裡面又可以分為三種對象:VIP客戶,普通客戶,快速客戶。取號機裡面的每個對象都要給來辦理業務的客戶一個號碼,同時,它還會為服務視窗提供一個應該服務的號碼。這個又是一個號碼管理器對象,因此它具有取號碼的功能、叫號的功能,服務視窗具有辦理業務的功能。因此物件導向的設計首先要設計這幾個對象,號碼機器()、號碼管理器()、服務視窗()、人員隨機產生。
類圖:
import java.util.ArrayList;
import java.util.List;
/*
* 這是號碼機器*/
public class NumbeiManager {
private int lastNumber=1;//記錄將要產生的號碼的號碼
private List<Integer> queueNumber=new ArrayList<Integer>();//面向介面和父類編程這就是專業List而不是ArrayList
public synchronized Integer generateNewManager(){//自己產生一個號碼 Integer可以避免如果當前沒有號碼的話會返回null,null不能轉成int,null 指標異常
queueNumber.add(lastNumber);
return lastNumber++;
}
public synchronized Integer fetchServiceNumber() //客戶來取號 原來返回是int,Integer可以避免如果當前沒有號碼的話會返回null,null不能轉成int,null 指標異常
{
Integer number=null;
if(queueNumber.size()>0)
number= queueNumber.remove(0);
return number;
}
}
package Bank;
/*
* 管理三個號碼的機器
* */
public class NumberMachine {
private NumbeiManager commonManager=new NumbeiManager(); //產生普通客戶號碼
private NumbeiManager expressManager=new NumbeiManager(); //產生快速客戶號碼
private NumbeiManager vipManager=new NumbeiManager();//產生vip客戶號碼
public NumbeiManager getCommonManager() {
return commonManager;
}
public NumbeiManager getExpressManager() {
return expressManager;
}
public NumbeiManager getVipManager() {
return vipManager;
}
//單例設計:將這個機器設計成單例並建立一個自己的對象,並對外提供一個介面
private NumberMachine(){}
private static NumberMachine instance=new NumberMachine(); //自身要提供一個對象
public static NumberMachine getInstance() //給外部提供一個各道執行個體的方法,類名直接要調用的靜態
{
return instance;
}
}
package Bank;
import java.util.Random;
import java.util.concurrent.Executors;
public class ServiceWindow {
private CustemerType type=CustemerType.COMMON;
private int windowId=1;
public void setType(CustemerType type) {
this.type = type;
}
public void setWindowId(int windowId) {
this.windowId = windowId;
}
public void start()
{
Executors.newSingleThreadExecutor().execute(new Runnable() {
@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="第"+windowId+"號"+type+"視窗";
System.out.println(windowName+"正在擷取任務");
Integer number=NumberMachine.getInstance().getCommonManager().fetchServiceNumber();
if(number!=null)
{
System.out.println(windowName+"為第"+number+"個"+type+"客戶服務");
long beginTime=System.currentTimeMillis();
int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serverTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serverTime);
} catch (Exception e) {
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"為第"+number+"個"+"普通客戶服務,耗時"+costTime/1000);
}
else
{
System.out.println(windowName+"沒有取到服務任務,先休息1秒");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void expressService() {
String windowName="第"+windowId+"號"+type+"視窗";
System.out.println(windowName+"正在擷取任務");
Integer number=NumberMachine.getInstance().getExpressManager().fetchServiceNumber();
if(number!=null)
{
System.out.println(windowName+"為第"+number+"個"+type+"客戶服務");
long beginTime=System.currentTimeMillis();
//int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
//long serverTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(Constants.MIN_SERVICE_TIME);
} catch (Exception e) {
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"為第"+number+"個"+type+"客戶服務,耗時"+costTime/1000);
}
else
{
System.out.println(windowName+"沒有取到服務任務");
commonService();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void vipService() {
String windowName="第"+windowId+"號"+type+"視窗";
System.out.println(windowName+"正在擷取任務");
Integer number=NumberMachine.getInstance().getVipManager().fetchServiceNumber();
if(number!=null)
{
System.out.println(windowName+"為第"+number+"個"+type+"客戶服務");
long beginTime=System.currentTimeMillis();
int maxRand=Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
long serverTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;
try {
Thread.sleep(serverTime);
} catch (Exception e) {
e.printStackTrace();
}
long costTime=System.currentTimeMillis()-beginTime;
System.out.println(windowName+"為第"+number+"個"+type+"客戶服務,耗時"+costTime/1000);
}
else
{
System.out.println(windowName+"沒有取到服務任務");
commonService();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package Bank;
public enum CustemerType {
COMMON,EXPRESS,VIP;
public String toString()
{
switch(this)
{
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return "VIP";
}
return null;
}
}
package Bank;
public class Constants {
public static int MAX_SERVICE_TIME=10000; //最大時間
public static int MIN_SERVICE_TIME=1000; //最小時間
public static int COMMON_CUSTOMER_INTERVAL_TIME=1;//普通客戶間隔時間
}
package Bank;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//5個普通視窗
for(int x=1;x<5;x++)
{
ServiceWindow commonWindow=new ServiceWindow();
commonWindow.setWindowId(x);
commonWindow.start();
}
//一個vip視窗
ServiceWindow VipWindow=new ServiceWindow();
VipWindow.setType(CustemerType.VIP);
VipWindow.start();
//一個expree視窗
ServiceWindow ExpressWindow=new ServiceWindow();
ExpressWindow.setType(CustemerType.EXPRESS);
ExpressWindow.start();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getCommonManager().generateNewManager();
System.out.println(number+"號普通客戶等待服務");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getExpressManager().generateNewManager();
System.out.println(number+"號快速客戶等待服務");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
TimeUnit.SECONDS);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
Integer number=NumberMachine.getInstance().getVipManager().generateNewManager();
System.out.println(number+"號VIP客戶等待服務");
}
},
0,
Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,
TimeUnit.SECONDS);
}
}