黑马程序员——【Java高新技术】——案例:银行业务调度系统

一、银行业务调度系统需求

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

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

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

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

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

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

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

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

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

二、面向对象的分析与设计

  1、有三种对应类型的客户:VIP客户,普通客户,快速客户 ,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务

  (1)首先,每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,我想到要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。

  (2)由于有三类客户,每类客户的号码编排都是完全独立的,所以,我想到本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。

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

  各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。

三、由需求分析而抽象出来的类及其方法的关系图

  

四、代码实现

  (一)NumberManager类

 1 package com.itheima.bank;
 2 /* NumberManager类:
 3  * 1.定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
 4  * 2.定义一个产生新号码的方法和获取马上要为之服务的号码的方法。
 5  * 3.这两个方法被不同的线程操作了相同的数据, 所以要进行同步。
 6  * */
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 public class NumberManager {
10     private int lastNumber = 0;
11     private List<Integer> queueNumber = new ArrayList<Integer>();
12     public synchronized Integer generateNewNumber(){
13         queueNumber.add(++lastNumber);
14         return lastNumber;
15     }
16     public synchronized Integer fetchNumber(){
17         if(queueNumber.size()>0){
18             return queueNumber.remove(0);
19         }else{
20             return null;
21         }
22     }
23 }

  (二)NumberMachine

 1 package com.itheima.bank;
 2
 3 /* NumberMachine类
 4  * 1.定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器。
 5  * 2.定义三个对应的方法来返回这三个NumberManager对象。
 6  * 3.将NumberMachine类设计成单例。
 7 */
 8 public class NumberMachine {
 9     private NumberManager commonManager = new NumberManager();
10     private NumberManager expressManager = new NumberManager();
11     private NumberManager vipManager = new NumberManager();
12
13     public NumberManager getCommonManager() {
14         return commonManager;
15     }
16     public NumberManager getExpressManager() {
17         return expressManager;
18     }
19     public NumberManager getVipManager() {
20         return vipManager;
21     }
22
23     private NumberMachine(){}
24     private static NumberMachine instance = new NumberMachine();
25     public static NumberMachine getInstance(){
26         return instance;
27     }
28 }

  (三)CustomerType枚举类

 1 package com.itheima.bank;
 2 /*
 3  * CustomerType枚举类
 4  * 1.系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
 5  * 2.重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。
 6  */
 7 public enum CustomerType {
 8     COMMON,EXPRESS,VIP;
 9     //返回中文名称
10     @Override
11     public String toString(){
12         switch(this){
13         case COMMON:
14             return "普通";
15         case EXPRESS:
16             return "快速";
17         case VIP:
18             return name();//name()返回此枚举常量的名称。
19         }
20         return null;
21     }
22 }

  (四)ServiceWindow

  1 package com.itheima.bank;
  2
  3 import java.util.Random;
  4 import java.util.concurrent.Executors;
  5 /*
  6  * ServiceWindow类
  7  * 1.定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
  8  * 2.定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
  9  */
 10 public class ServiceWindow {
 11     private CustomerType type = CustomerType.COMMON;
 12     private int number = 1;
 13
 14     public void setNumber(int number) {
 15         this.number = number;
 16     }
 17
 18     public void setType(CustomerType type) {
 19         this.type = type;
 20     }
 21
 22     public void start(){
 23         Executors.newSingleThreadExecutor().execute(new Runnable() {
 24             public void run() {
 25                 while(true){
 26                 switch (type) {
 27                 case COMMON:
 28                     commonService();
 29                     break;
 30                 case EXPRESS:
 31                     expressService();
 32                     break;
 33                 case VIP:
 34                     vipService();
 35                     break;
 36                 }
 37                 }
 38             }
 39         });
 40     }
 41
 42     private void commonService() {
 43             Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
 44             String windowName = "第" + number + "号" + type + "窗口";
 45             System.out.println(windowName + "开始获取普通任务!");
 46             if (serviceNumber != null) {
 47                 System.out.println(windowName + "开始为第" + serviceNumber + "号普通客户服务");
 48                 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
 49                 int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_TIME;
 50
 51                 try {
 52                     Thread.sleep(serviceTime);
 53                 } catch (InterruptedException e) {
 54                     e.printStackTrace();
 55                 }
 56                 System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime / 1000 + "秒");
 57
 58             } else {
 59                 System.out.println(windowName + "没有取到普通任务,正在空闲一秒");
 60                 try {
 61                     Thread.sleep(1000);
 62                 } catch (InterruptedException e) {
 63                     e.printStackTrace();
 64                 }
 65             }
 66         }
 67
 68     private void expressService() {
 69             Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
 70             String windowName = "第" + number + "号" + type + "窗口";
 71             System.out.println(windowName + "开始获取快速任务!");
 72             if (serviceNumber != null) {
 73                 System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");
 74                 int serviceTime = Constants.MIN_SERVICE_TIME;
 75                 try {
 76                     Thread.sleep(serviceTime);
 77                 } catch (InterruptedException e) {
 78                     e.printStackTrace();
 79                 }
 80                 System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime / 1000 + "秒");
 81             } else {
 82                 System.out.println(windowName + "没有取到快速任务");
 83                 commonService();
 84             }
 85         }
 86
 87     private void vipService() {
 88             Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
 89             String windowName = "第" + number + "号" + type + "窗口";
 90             System.out.println(windowName + "正在获取vip任务");
 91             if (serviceNumber != null) {
 92                 System.out.println(windowName + "开始为第" + serviceNumber + "号vip客户服务");
 93                 int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
 94                 int serviceTime = new Random().nextInt(maxRandom)+1+Constants.MIN_SERVICE_TIME;
 95                 try {
 96                     Thread.sleep(serviceTime);
 97                 } catch (InterruptedException e) {
 98                     e.printStackTrace();
 99                 }
100                 System.out.println(windowName + "完成为第" + serviceNumber + "号vip客户服务,总共耗时" + serviceTime / 1000 + "秒");
101             } else {
102                 System.out.println(windowName + "没有取到vip任务!");
103                 commonService();
104             }
105         }
106 }

  (五)Constants

 1 package com.itheima.bank;
 2
 3 /*Constants类,定义三个常量:
 4  * 1.MAX_SERVICE_TIME:客户办理业务所需时间有最大值
 5  * 2.MIN_SERVICE_TIME:客户办理业务所需时间有最小值
 6  * 3.COMMON_CUSTOMER_INTERVAL_TIME:普通客户出现的时间间隔
 7  * */
 8 public class Constants {
 9     public static int MAX_SERVICE_TIME = 10000;
10     public static int MIN_SERVICE_TIME = 1000;
11     /* 每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
12      * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,
13      * 1秒钟产生一个普通客户比较合理,*/
14     public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
15 }

  (六)MainClass

 1 package com.itheima.bank;
 2
 3 import java.util.concurrent.Executors;
 4 import java.util.concurrent.TimeUnit;
 5 public class MainClass {
 6     /*    MainClass类
 7      *1.用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
 8      * 2.接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
 9      */
10     public static void main(String[] args) {
11
12         //产生4个普通窗口
13         for(int i=1;i<5;i++){
14             ServiceWindow window = new ServiceWindow();
15             window.setNumber(i);
16             window.start();
17         }
18
19         //产生1个快速窗口
20         ServiceWindow expressWindow = new ServiceWindow();
21         expressWindow.setType(CustomerType.EXPRESS);
22         expressWindow.start();
23
24         //产生1个VIP窗口
25         ServiceWindow vipWindow = new ServiceWindow();
26         vipWindow.setType(CustomerType.VIP);
27         vipWindow.start();
28
29         //普通客户拿号
30         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
31                 new Runnable(){
32                     public void run() {
33                         Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();
34                         System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");
35                     }
36                 },
37                 0,
38                 Constants.COMMON_CUSTOMER_INTERVAL_TIME, //每隔1秒钟,有一个普通客户
39                 TimeUnit.SECONDS
40                 );
41
42         //快速客户拿号
43         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
44                 new Runnable(){
45                     public void run(){
46                         Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();
47                         System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");
48                     }
49                 },
50                 0,
51                 Constants.COMMON_CUSTOMER_INTERVAL_TIME*2,
52                 TimeUnit.SECONDS
53                 );
54         //VIP客户拿号
55         Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
56                 new Runnable(){
57                     public void run(){
58                         Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();
59                         System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");
60                     }
61                 },
62                 0,
63                 Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
64                 TimeUnit.SECONDS
65                 );
66     }
67 }
时间: 2024-10-23 05:23:22

黑马程序员——【Java高新技术】——案例:银行业务调度系统的相关文章

黑马程序员-JAVA学习之银行业务调度系统分析与实现

--------android培训.java培训.期待与你交流!-------- 银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下:1 银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口.2 有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费.电话费之类业务的客户).3 异步随机生成各种类型的客户,生成各类型用户的概率比例为:VIP客户 :普通客户 :快速客户 = 1 :6 :3.4 客户办理业务所需时间有最大值和最小值,在该

黑马程序员——Java高新技术代理

代理 普通代理 很多时候,我们使用别人代码往往会发现别人代码的功能并不是十分符合我们的需求,调用别人的方法的时候,总是先new一个对象,然后我们的前处理做完,然后调用别人代码的方法,再加入后处理,这样做往往十分麻烦.代理就为其他类提供了一种控制其对象的方法.代理类和委托类必须实现同一个接口,这样代理类才能在需要的时候代替委托类对象,执行委托类的方法. interface Solution{ public void doSomething(); } //委托类Demo实现了接口 class Dem

黑马程序员——java高新技术(新特性、反射、泛型)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- java高新技术 第一部分——JDK1.5新特性 1.增强for循环 格式: for(元素类型 变量名 : Collection集合 & 数组 ) { }//增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器 高级for循环和传统for循环的区别: 高级for循环在使用时,必须要明确被遍历的目标.这个目标,可以是Collection集合或者数组,如果遍历Collec

黑马程序员——Java高新技术——反射机制

点击打开链接 点击打开链接 点击打开链接 android培训.<a">点击打开链接 点击打开链接 java培训.期待与您交流!">点击打开链接 点击打开链接 反射的基石--Class类 Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class. Class类没有构造函数,不能new对象.怎么得到Class类的实例,有3中方法: ①类名.Class    Class  c1=Date.class; ②对象.getClass 获取对象所属的字

黑马程序员——Java高新技术——反射的复写

由于第一段视频学习效果不理想,希望重新看一遍反射视频,并多方面寻找资料,重新写一遍总结,以期java能力早日提高. Java——反射 一.Class类 Class 类的实例表示正在运行的 Java 应用程序中的类和接口.所以,Class可以提供方法获得动态的java类中的各个属性: (由定义可以知道Class创建的思路就是获得某一个特定java类的信息然后传给Class的对象,那么具体怎么做呢?) 这里说得java类的信息指的就是该java类的计算机的字节码:传给 Class cls1: 所以有

黑马程序员----Java高新技术之反射学习总结

------- android培训.java培训.期待与您交流! ---------- 反射的概念. 1.Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 精妙的总结就是:反射就是将Java类中的各个成分映射成相应的Java类. 3.在Java中,描述事物的各种类同样也是一种事物,也可以用面向对象的方法来描述,即也有一个类来描述众多的J

黑马程序员——java高新技术——网络编程

点击打开链接 点击打开链接 点击打开链接 android培训.<a">点击打开链接 点击打开链接 java培训.期待与您交流!">点击打开链接 点击打开链接 网络编程 网络模型 l   OSI参考模型 l   TCP/IP参考模型 网络通讯要素 l   IP地址:网络中设备的标识,不易记忆,可用主机名,本地回环地址,127.0.0.1  主机名:localhost l   端口号:用于标识进程的逻辑地址,不同进程的标识,有效端口:0~65535,其中0~1024系统使

黑马程序员——JAVA高新技术——反射

----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 一.对于反射的概念 对于JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby

黑马程序员——java高新技术——IO其他流对象

点击打开链接 点击打开链接 点击打开链接 android培训.<a">点击打开链接 点击打开链接 java培训.期待与您交流!">点击打开链接 点击打开链接 IO其他对象 PrintStream:字节打印流.为其他输出流添加了功能,提供了打印方法,可以将各种数据类型的数据原样打印. 构造函数可以接受的参数类型:file对象,字符串路径,字节输出流. 方法:println():打印各种基本数据类型. PrintWrite:字符打印流.构造函数可以接受的参数类型:file

黑马程序员——Java面试题之银行业务调度系统

                       android培训.java培训.期待与您交流!  对象分析: 1.客户类按照业务分类,客户可以分成三类. public enum Custommer { COMMON ,VIP , EXPRESS; public String toString(){ String name =null ; switch (this ){ case COMMON : name ="普通" ; break; case VIP : name ="VI