您的位置:首页 > 编程语言 > Java开发

JavaSE基础学习笔记-提高篇-银行业务调度系统

2013-11-23 13:41 489 查看
有了前一个交通灯系统的面向对象分析经验,在对该系统进行面向对象分析时,更容易理解了,下面是需求说明和简单是分析过程

需求说明:

Ø 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

Ø 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

Ø 异步随机生成各种类型的客户,生成各类型用户的概率比例为:

VIP客户 :普通客户 :快速客户 = 1 :6 :3。

Ø 客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

Ø 各类型客户在其对应窗口按顺序依次办理业务。

Ø 当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

Ø 随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

面向对象的分析与设计

有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 :快速客户 = 1 :6 :3。

我们都指定,每一个客户都与银行的取号机打印出的一个号码是对应的,所以想到有一个号码管理器对象,让这个对象不断的产生号码,就等于来了客户。

由于有3类客户,每类客户的号码编排都是独立的,所以系统要产生三个号码管理器对象来各自管理一类客户的号码编排,这三个号码管理器由统一的一个号码机器进行管理,这个号码机器在整个系统中只能有一个,所以设计成单例模式

各类型客户在其对应窗口按顺序依次办理业务,准确的说应该是窗口依次叫号

各个窗口怎么知道该叫那个号呢?它一定是问的业务与之相对应的号码管理器,即服务

窗口每次找号码管理器获取当前要被服务的号码

由此分析可以对业务需求简化,总结出该程序应该有三个类,分别是:NumbeMachine

(号码机器,用来为客户产生号码),NumberManager(号码管理器,为三类客户生成

彼此独立的号码队列) ,ServiceWindow(服务窗口,)

源代码如下(代码程序由张孝祥老师编写,本人只是照着敲一遍,默敲一遍):

/**
* 定义客户类型
* */
public enum CustomType {
COMMON,VIP,EXPRESS;

public String toString(){
switch(this){
case COMMON:
return "普通";
case VIP:
return "vip";
case EXPRESS:
return "快速";
}
return null;
}
}
<pre code_snippet_id="78527" snippet_file_name="blog_20131123_2_647219" name="code" class="java">/**定义服务过程中随机产生的最长时间和最短时间*/
public class Constants {
public static int maxServiceTime = 10000;
public static int minServiceTime = 1000;
}


import java.util.*;
/**
* 号码管理器,号码生成器每次成产一个新号码时,根据客户类型调用NumberManager对象来获取依次顺延的号码
*
* 银行窗口在叫号时,要用到相应客户类型的NumberManager对象来获取即将要被服务的客户号码
* */
public class NumberManager {
//队列的尾号
private int lastNumber = 1;
//用集合吧产生的队列进行封装,方便操作
private List<Integer> numberQueue = new ArrayList<Integer>();
//生产新号码                                   //
public synchronized Integer generateNewNumber(){   //由于号码机器和服务窗口要分别调用generateNewNumber和
numberQueue.add(lastNumber);               //fetchServiceNumber,这两个方法中又操作了相同元素,
return lastNumber++;                       //所以要对这两方法进行同步处理
}

//为服务窗口提供将要被服务的号码   用Integer防止null异常
public synchronized Integer fetchServiceNumber(){
//返回第一个元素并移除
if(numberQueue.size() > 0){
return numberQueue.remove(0);
}else{
return null;
}
}

}


/**
* 号码机器,为客户产生号码
* */
public class NumberMachine {
//定义三个NumberManager对象分别对应普通客户,快速客户和VIP客户
private NumberManager commonClient = new NumberManager();
private NumberManager expressClient = new NumberManager();
private NumberManager VIPClient = new NumberManager();

public NumberManager getCommonClient() {
return commonClient;
}
public NumberManager getExpressClient() {
return expressClient;
}
public NumberManager getVIPClient() {
return VIPClient;
}

//因为NumberMachine在整个程序中是唯一的,所以要设计成单例模式

//构造方法私有化
private NumberMachine(){}

//创建静态方法,返回NumberMachine对象
private static NumberMachine machine = new NumberMachine();
public static NumberMachine newInstance(){
return machine;

}

}


import java.util.Random;
import java.util.concurrent.Executors;
/**
* 服务窗口
* */
public class ServiceWindow {
// 定义客户类型,以便进行服务窗口的区分
protected CustomType type = CustomType.COMMON;
// 定义窗口号码
protected int windowID = 1;
//定义一个启动服务的方法
private Integer comNum = null;

public void setType(CustomType type) {
this.type = type;
}

public void setWindowID(int windowID) {
this.windowID = windowID;
}

public void start() {
/**
* 窗口服务启动之后,就会一直不停的进行循环服务,所以对每一种类客户的服务都设定一个线程
* */
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
// 线程中的程序不停的获取客户号码
while (true) {
// 确定客户类型
switch (type) {
case COMMON:
commonService();
break;
case VIP:
expressService();
break;
case EXPRESS:
break;
default :
break;
}

}
}
});
}

public void commonService() {
// 定义窗口名称
String windowName = "第" + windowID + "号 " + type + " 窗口";
System.out.println(windowName + "正在获取任务...");
comNum = NumberMachine.newInstance().getCommonClient().fetchServiceNumber();
if (comNum != null) {
System.out.println(windowID + "号 " + type + " 窗正在为第" + comNum + "个" + CustomType.COMMON + "客户服务");
long beginTime = System.currentTimeMillis();
int maxTime = Constants.maxServiceTime - Constants.minServiceTime;
// 获取服务的随机时间 1 ~ 10秒
long serviceTime = new Random().nextInt(maxTime) + 1;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(windowName + "为" + comNum + "号"+type+"客户服务了"
+ (endTime - beginTime) / 1000 + "秒");
System.out.println();
} else {
try {
System.out.println(windowName + "没有取到任务");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void expressService(){
// 定义窗口名称
String windowName = "第" + windowID + "号 " + type + " 窗口";
System.out.println(windowName + "正在获取任务...");
comNum = NumberMachine.newInstance().getExpressClient().fetchServiceNumber();
if (comNum != null) {
System.out.println(windowID + "号 " + type + " 窗口正在为第" + comNum + "个" + CustomType.EXPRESS + "客户服务");
try {
Thread.sleep(Constants.minServiceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(windowName + "为" + comNum + "号"+type+"客户服务了"
+ Constants.minServiceTime/1000 + "秒");
System.out.println();
} else {
System.out.println(windowName + "没有取到任务");
commonService();
}
}

public void vipService() {
// 定义窗口名称
String windowName = "第" + windowID + "号 " + type + " 窗口";
System.out.println(windowName + "正在获取任务...");
comNum = NumberMachine.newInstance().getVIPClient().fetchServiceNumber();

if (comNum != null) {
System.out.println(windowID + "号 " + type + " 窗口正在为第" + comNum + "个" + CustomType.VIP + "客户服务");
long beginTime = System.currentTimeMillis();
int maxTime = Constants.maxServiceTime - Constants.minServiceTime;
// 获取服务的随机时间 1 ~ 10秒
long serviceTime = new Random().nextInt(maxTime) + 1;
try {
Thread.sleep(serviceTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(windowName + "为" + comNum + "号"+type+"客户服务了"
+ (endTime - beginTime) / 1000 + "秒");
System.out.println();
} else {
System.out.println(windowName + "没有取到任务");
commonService();
}
}

}


import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MainClass {
public static void main(String []args){
//创建窗口对象
for(int i = 1;i < 5;i ++){
ServiceWindow commonWindow = new ServiceWindow();
commonWindow.setWindowID(i);
commonWindow.start();
}
ServiceWindow vipWindow = new ServiceWindow();
vipWindow.setType(CustomType.VIP);
vipWindow.setWindowID(5);
vipWindow.start();

ServiceWindow expressWindow = new ServiceWindow();
expressWindow.setType(CustomType.EXPRESS);
expressWindow.setWindowID(6);
expressWindow.start();

//模拟普通客户取号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
public void run(){
Integer num = NumberMachine.newInstance().getCommonClient().generateNewNumber();
System.out.println(num + "号普通客户等待服务");
}
}, 0, 3, TimeUnit.SECONDS);
//模拟快速客户取号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
public void run(){
Integer num = NumberMachine.newInstance().getExpressClient().generateNewNumber();
System.out.println(num + "号普通客户等待服务");
}
}, 0, 1, TimeUnit.SECONDS);
//模拟vip客户取号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable(){
public void run(){
Integer num = NumberMachine.newInstance().getVIPClient().generateNewNumber();
System.out.println(num + "号普通客户等待服务");
}
}, 0, 6, TimeUnit.SECONDS);
}
}





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: