模拟银行业务调度系统逻辑

需求

模拟实现银行业务调度系统逻辑,具体需求如下:

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

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

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

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

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

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

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

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

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

分析

我们知道客户去银行办理业务,首先要去取号机取号,然后等待窗口叫号,那么窗口是通过什么叫号的呢,就是根据取号机内部产生和维护的不同的业务队列来完成的

所以

涉及的对象有:业务窗口、客户、取号机、业务类型以及取号机内部维护的业务队列

为了简化设计,用字符串形式代替客户信息,主要实现系统逻辑为主

面向对象分析与设计

业务类型BusinessType类:

采用枚举的方式,创建3个实例分别表示普通业务、快速业务、VIP业务

内部维护的业务队列Queue类:

内部维护一个集合用来存放队列中的客户信息

以及一个整型变量用来表示当天的客户队列号

实现加入一个客户到队列的方法

以及从队列中取出一个客户的方法(即叫号过程)

取号机TicketMachine类:

简化编程,我们将取号机设计成一个单例

内部维护三个不同业务类型的队列

对外提供取号方法给用户

提供获取队列方法给业务窗口

业务窗口Windows类:

业务窗口属性有:业务类型及窗口编号

对外提供开始业务的方法供银行调度

思考:

在对业务窗口进行设计的时候发现,虽然各窗口同属一类,但在提供服务的过程不尽相同,所以考虑的两种实现方式,如图

bank

  • 第一种就是考虑到在开展业务的时候各窗口的代码有不同之处,所以考虑用这种方式来设计,将不同的业务类型的窗口分配到不同的类
  • 第二种是直接将所有业务类型的服务代码写在同一个类中

由于不太懂设计模式,个人的感觉是,这里主要实现的是系统逻辑,所以每个窗口的服务代码差异并没有想象的大,故采用第二种方式

如果是一个比较系统的需要长期维护的项目,我会采用第一种,确保每个类的单一功能

代码实现

业务类型BusinessType类:

   1: /**
   2:  * 业务类型
   3:  * @author Shawn
   4:  *
   5:  */
   6: public enum BusinessType {
   7:     GENERAL,//普通业务类型
   8:     QUICK,//快速业务类型
   9:     VIP;//VIP业务类型
  10:     
  11:     @Override
  12:     public String toString() {
  13:         switch(this){
  14:         case GENERAL:
  15:             return "普通";
  16:         case QUICK:
  17:             return "快速";
  18:         case VIP:
  19:             return "VIP";
  20:         }
  21:         return null;
  22:     }
  23: }

用户队列Queue类:

   1: /**
   2:  * 用户队列
   3:  * @author Shawn
   4:  *
   5:  */
   6: public class Queue {
   7:     
   8:     private BusinessType businessType;//队列的业务类型
   9:     private int customerNum = 1;//记录用户队列号
  10:     List<String> queue = new LinkedList<String>();//队列载体
  11:     
  12:     public Queue(BusinessType businessType) {
  13:         super();
  14:         this.businessType = businessType;
  15:     }
  16:     
  17:     //产生新的号码,加入到队列
  18:     public synchronized String generateNewCustomer(){
  19:         String name = businessType+"客户_"+(customerNum++)+"号";
  20:         if(queue.add(name))
  21:             return name;
  22:         else
  23:             return null;
  24:     }
  25:     
  26:     //从队列中取出第一个客户
  27:     public synchronized String getCustomer(){
  28:         if(!isEmpty())
  29:             return queue.remove(0);
  30:         else 
  31:             return null;
  32:     }
  33:     
  34:     //判断队列是否为空,即是否有客户等待业务
  35:     public synchronized boolean isEmpty(){
  36:         if(queue.size() > 0)
  37:             return false;
  38:         else
  39:             return true;
  40:     }
  41: }

取号机TicketMachine类:

   1: /**
   2:  * 取号机
   3:  * @author Shawn
   4:  *
   5:  */
   6: public class TicketMachine {
   7:     
   8:     //内部维护的三个业务队列
   9:     private Queue generalQueue = new Queue(BusinessType.GENERAL);
  10:     private Queue quickQueue = new Queue(BusinessType.QUICK);
  11:     private Queue vipQueue = new Queue(BusinessType.VIP);
  12:     
  13:     //获取相关业务队列的接口
  14:     public Queue getQueue(BusinessType businessType){
  15:         switch(businessType){
  16:         case GENERAL:
  17:             return generalQueue;
  18:         case QUICK:
  19:             return quickQueue;
  20:         case VIP:
  21:             return vipQueue;
  22:         }
  23:         return null;
  24:     }
  25:     
  26:     //针对不同业务,加入新的客户到对应队列
  27:     public String generateTicket(BusinessType businessType){
  28:         switch(businessType){
  29:         case GENERAL:
  30:             return generalQueue.generateNewCustomer();
  31:         case QUICK:
  32:             return quickQueue.generateNewCustomer();
  33:         case VIP:
  34:             return vipQueue.generateNewCustomer();
  35:         }
  36:         return null;
  37:     }
  38:     //单例实现
  39:     private TicketMachine(){}
  40:     private static TicketMachine machineInstance = new TicketMachine();
  41:     public static TicketMachine getInstance(){
  42:         return machineInstance;
  43:     }
  44: }

业务窗口Windows类:

   1: /**
   2:  * 业务窗口
   3:  * @author Shawn
   4:  *
   5:  */
   6: public class Windows {
   7:     private BusinessType businessType;//窗口业务类型
   8:     private int winNum;//窗口编号
   9:     private boolean available = false;//窗口开放状态
  10:     
  11:     public Windows(BusinessType businessType,int winNum) {
  12:         super();
  13:         this.businessType = businessType;
  14:         this.winNum = winNum;
  15:     }
  16:     
  17:     //开始业务
  18:     public void start(){
  19:         available = true;
  20:         System.out.println(this+"开始服务!");
  21:         
  22:         //创建新的线程开始不同窗口的业务
  23:         ExecutorService pool = Executors.newSingleThreadExecutor();
  24:         pool.execute(new Runnable(){
  25:             public void run(){
  26:                 switch(businessType){
  27:                 case GENERAL:
  28:                     while(available){
  29:                         generalService();
  30:                     }
  31:                 case QUICK:
  32:                     while(available){
  33:                         quickService();
  34:                     }    
  35:                 case VIP:
  36:                     while(available){
  37:                         vipService();
  38:                     }    
  39:                 }
  40:             }
  41:         });
  42:     }
  43:     //普通业务窗口服务过程
  44:     private void generalService(){
  45:         //普通业务只需要获得普通用户队列
  46:         Queue queue = TicketMachine.getInstance().getQueue(BusinessType.GENERAL);
  47:         //如果队列不为空,则开始叫号并模拟服务
  48:         if(!queue.isEmpty()){
  49:             String name = queue.getCustomer();
  50:             System.out.println(this+"正在为 "+name+"服务~");
  51:             int time = generalCustomerServicing();
  52:             //System.out.println(this+"服务完毕,耗时"+time+"秒");
  53:         }
  54:         else{
  55:             //System.out.println(this+"正在等待客户...");
  56:             try {
  57:                 Thread.sleep(1000);
  58:             } catch (InterruptedException e) {
  59:                 // TODO Auto-generated catch block
  60:                 e.printStackTrace();
  61:             }
  62:         }
  63:     }
  64:     //快速窗口业务服务过程
  65:     private void quickService(){
  66:         //快速窗口需要得到快速队列以及普通队列
  67:         Queue quickQueue = TicketMachine.getInstance().getQueue(BusinessType.QUICK);
  68:         Queue generalQueue = TicketMachine.getInstance().getQueue(BusinessType.GENERAL);
  69:         
  70:         //首先判断快速队列
  71:         if(!quickQueue.isEmpty()){
  72:             String name = quickQueue.getCustomer();
  73:             System.out.println(this+"正在为 "+name+"服务~");
  74:             int time = quickCustomerServicing();
  75:             //System.out.println(this+"服务完毕,耗时"+time+"秒");
  76:         }
  77:         //若快速队列没有等待客户,则考虑普通队列
  78:         else if(!generalQueue.isEmpty()){
  79:             String name = generalQueue.getCustomer();
  80:             System.out.println(this+"正在为 "+name+"服务~");
  81:             int time = generalCustomerServicing();
  82:             //System.out.println(this+"服务完毕,耗时"+time+"秒");
  83:         }
  84:         else{
  85:             //System.out.println(this+"正在等待客户...");
  86:             try {
  87:                 Thread.sleep(1000);
  88:             } catch (InterruptedException e) {
  89:                 // TODO Auto-generated catch block
  90:                 e.printStackTrace();
  91:             }
  92:         }
  93:     }
  94:     //vip窗口业务服务过程
  95:     private void vipService(){
  96:         //vip窗口需要得到的vip队列以及普通队列
  97:         Queue vipQueue = TicketMachine.getInstance().getQueue(BusinessType.VIP);
  98:         Queue generalQueue = TicketMachine.getInstance().getQueue(BusinessType.GENERAL);
  99:         
 100:         //如果vip队列不为空,则取出vip客户处理
 101:         if(!vipQueue.isEmpty()){
 102:             String name = vipQueue.getCustomer();
 103:             System.out.println(this+"正在为 "+name+"服务~");
 104:             int time = vipCustomerServicing();
 105:             //System.out.println(this+"服务完毕,耗时"+time+"秒");
 106:         }
 107:         //若vip队列为空,则考虑普通队列
 108:         else if(!generalQueue.isEmpty()){
 109:             String name = generalQueue.getCustomer();
 110:             System.out.println(this+"正在为 "+name+"服务~");
 111:             int time = generalCustomerServicing();
 112:             //System.out.println(this+"服务完毕,耗时"+time+"秒");
 113:         }
 114:         else{
 115:             //System.out.println(this+"正在等待客户...");
 116:             try {
 117:                 Thread.sleep(1000);
 118:             } catch (InterruptedException e) {
 119:                 // TODO Auto-generated catch block
 120:                 e.printStackTrace();
 121:             }
 122:         }
 123:         
 124:     }
 125:     //服务普通客户的模拟时间
 126:     private int generalCustomerServicing(){
 127:         int time = new Random().nextInt(
 128:                 Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME)+
 129:                 Constants.MIN_SERVICE_TIME;
 130:         try {
 131:             Thread.sleep(time*1000);
 132:         } catch (InterruptedException e) {
 133:             // TODO Auto-generated catch block
 134:             e.printStackTrace();
 135:         }
 136:         return time;
 137:     }
 138:     //服务快速客户的模拟时间
 139:     private int quickCustomerServicing(){
 140:         int time = Constants.MIN_SERVICE_TIME;
 141:         try {
 142:             Thread.sleep(time*1000);
 143:         } catch (InterruptedException e) {
 144:             // TODO Auto-generated catch block
 145:             e.printStackTrace();
 146:         }
 147:         return time;
 148:     }
 149:     //服务vip客户的模拟时间
 150:     private int vipCustomerServicing(){
 151:         int time = new Random().nextInt(
 152:                     Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME)+
 153:                     Constants.MIN_SERVICE_TIME;
 154:         try {
 155:             Thread.sleep(time*1000);
 156:         } catch (InterruptedException e) {
 157:             // TODO Auto-generated catch block
 158:             e.printStackTrace();
 159:         }
 160:         return time;
 161:     }
 162:     
 163:     @Override
 164:     public String toString() {
 165:         // TODO Auto-generated method stub
 166:         return businessType+"窗口"+winNum+"号";
 167:     }
 168: }
最后,统一维护的常量类,以及测试代码
   1: /**
   2:  * 统一维护的常量信息
   3:  * @author Shawn
   4:  *
   5:  */
   6: public class Constants {
   7:     
   8:     //客户服务的最大时间    10s
   9:     public static int MAX_SERVICE_TIME = 10;
  10:     //客户服务的最小时间    5s
  11:     public static int MIN_SERVICE_TIME = 5;
  12:     
  13:     //产生普通客户的间隔时间    1s
  14:     public static int COMMON_ITTERVAL_TIME = 1;
  15: }
   1: public class MainClass {
   2:  
   3:     /**
   4:      * 测试代码
   5:      * @param args
   6:      */
   7:     public static void main(String[] args) {
   8:         ScheduledExecutorService timer = null;
   9:         
  10:         //建立普通窗口
  11:         for(int i = 1 ; i <= 4 ; i ++){
  12:             new Windows(BusinessType.GENERAL,i).start();
  13:         }
  14:         //建立快速窗口
  15:         new Windows(BusinessType.QUICK,1).start();
  16:         //建立VIP窗口
  17:         new Windows(BusinessType.VIP,1).start();
  18:         //普通用户拿票
  19:         timer = Executors.newScheduledThreadPool(1);
  20:         timer.scheduleAtFixedRate(
  21:                 new Runnable(){
  22:                     public void run(){
  23:                         String name = TicketMachine.getInstance().generateTicket(BusinessType.GENERAL);
  24:                         //System.out.println(name + "正在等待服务...");
  25:                     }
  26:                 }, 
  27:                 1, 
  28:                 Constants.COMMON_ITTERVAL_TIME, 
  29:                 TimeUnit.SECONDS);
  30:         //快速用户拿票
  31:         timer = Executors.newScheduledThreadPool(1);
  32:         timer.scheduleAtFixedRate(
  33:                 new Runnable(){
  34:                     public void run(){
  35:                         String name = TicketMachine.getInstance().generateTicket(BusinessType.QUICK);
  36:                         //System.out.println(name + "正在等待服务...");
  37:                     }
  38:                 }, 
  39:                 1, 
  40:                 Constants.COMMON_ITTERVAL_TIME*2, 
  41:                 TimeUnit.SECONDS);
  42:         
  43:         //普通用户拿票
  44:         timer = Executors.newScheduledThreadPool(1);
  45:         timer.scheduleAtFixedRate(
  46:                 new Runnable(){
  47:                     public void run(){
  48:                         String name = TicketMachine.getInstance().generateTicket(BusinessType.VIP);
  49:                         //System.out.println(name + "正在等待服务...");
  50:                     }
  51:                 }, 
  52:                 1, 
  53:                 Constants.COMMON_ITTERVAL_TIME*6, 
  54:                 TimeUnit.SECONDS);    
  55:     }
  56: }

总结

基本实现了银行取号调度的系统逻辑

在程序扩展性上产生了比较多的思考和疑惑,抓紧时间摸索设计模式,希望今后可以写出精良的代码

posted @ 2013-12-10 05:24  ShawnWithSmallEyes  阅读(1046)  评论(0编辑  收藏  举报