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


    需求

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

    银行内有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: }

    总结

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

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

  • 相关阅读:
    在Ubuntu下编译Qt错误及处理办法
    二、数字电路中常见器件应用分析-三极管
    2.NB-IoT及通信协议
    1.编写一个shell脚本
    7.STM32中GPIO理解
    (引用)!Unicode,GBK以及UTF8的联系和区别
    java垃圾回收
    java集合框架概述
    RSA实现(java)
    RSA算法(非对称加密)
  • 原文地址:https://www.cnblogs.com/ShawnWithSmallEyes/p/3466751.html
Copyright © 2020-2023  润新知