黑马程序员——高新技术(银行业务调度系统)

来源:互联网 发布:蔡司三坐标软件 编辑:程序博客网 时间:2024/05/24 13:28

------- android培训、java培训、期待与您交流! ----------

银行业务调度系统:

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

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

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

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

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

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

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

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

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

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

解题思路

面向对象的分析和设计:

(一)有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务。
  1.首先,经常在银行办理业务的人更有利于理解本系统,例如,我经常陪老婆跑银行,对银行的这个业务算是比较熟悉了,我知道每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,我想到要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。
  2.由于有三类客户,每类客户的号码编排都是完全独立的,所以,我想到本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。
(二)各类型客户在其对应窗口按顺序依次办理业务 ,准确地说,应该是窗口依次叫号。
  1.各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。
  2.如果我不是多次亲身经历银行的这种业务,再加之积累了大量面向对象的应用开发经验,我也不知道能否轻松进行这种设计,能否发掘出其中隐含的对象信息,我真说不出具体的经验是什么,就是日积月累出来的一种感觉。                

·   类的编码实现

(一)NumberManager类
  1.定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
  2.定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。

源码如下:

package com.isosoft.bank;import java.util.ArrayList;import java.util.List;public classNumberManager {private int lastNumber =1;private List<Integer> queueNumber= newArrayList<Integer>();public synchronized Integer generateNewManager(){  queueNumber.add(lastNumber);  return lastNumber++;}  /**  * @author   */public synchronized Integer fetchServiceNumber(){  Integer number= null;  if(queueNumber.size()>0){   number= queueNumber.remove(0);  }   return number;}}


(二)NumberMachine类
  1.定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
  2.将NumberMachine类设计成单例。
源码如下:

package com.isosoft.bank;public classNumberMachine {           /**            * @author             */public NumberManager commonManager =new NumberManager();public NumberManager expressManager =new NumberManager();public NumberManager vipManager =new NumberManager();public NumberManager getCommonManager(){  return commonManager;}public NumberManager getExpressManager(){  return expressManager;}public NumberManager getVipManager(){  return vipManager;}   private NumberMachine(){}    public static NumberMachine getInstance(){          return instance;   }     private static NumberMachine instance= newNumberMachine();}



(三)CustomerType枚举类
  1.系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
  2.重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的。
源码如下:三)CustomerType枚举类
  1.系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
  2.重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的。
源码如下:三)CustomerType枚举类
  1.系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
  2.重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的。
源码如下:

 

package com.isosoft.bank;public enum CustomerType {COMMON,EXPRESS,VIP;public String toString(){/**  * @author   */  switch(this){  case COMMON:   return "普通";  case EXPRESS:   return "快捷";  case VIP:   return name();  }  return null;}}


四)ServiceWindow类
  1.定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
  2.定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
源码如下:

package com.isosoft.bank;import java.util.Random;import java.util.concurrent.Executors;   /* 没有把VIP窗口和快速窗口做成子类,是因为实际业务中的普通窗口可以随时被设置为VIP窗口和快速窗口. */public class ServiceWindow {  /**  * @author   */private CustomerType type = CustomerType.COMMON;private int windowId = 1;private String windoName;public void setType(CustomerType type) {  this.type = type;}public void setWindowId(int windowId) {  this.windowId = windowId;}public void start(){  Executors.newCachedThreadPool().execute(new Runnable(){   public void run(){    while(true){//下面这种写法的运行效率低,最好是把while放在case下面     // NumberMachine.getInstance().getCommonManager();     switch(type){     case COMMON:      commonService();      break;     case EXPRESS:      expressService();      break;     case VIP:      vipService();      break;     }    }   }  });}   private void commonService() {    String windowName = "第"+windowId+"号"+type+"窗口";    Integer number =NumberMachine.getInstance().getCommonManager().fetchServiceNumber();    System.out.println(windowName+"正在获取任务");    if(number != null){     System.out.println(windowName+"为第"+number+"个普通客户服务");     //long beginTime = System.currentTimeMillis();     int maxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;     long serviceTime=newRandom().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;      try {       Thread.sleep(serviceTime);      } catch (InterruptedException e) {       e.printStackTrace();      }        //long costTime = System.currentTimeMillis();     System.out.println(windowName+"为第"+number+"个"+"普通"+"客户完成服务,耗时"+serviceTime/1000+"秒");    }else{     System.out.println(windowName+"没有取到任务,先休息1秒钟!");     try {      Thread.sleep(1000);     } catch (InterruptedException e) {      e.printStackTrace();     }    }   }   private void expressService() {    String windowName = "第"+windowId+"号"+type+"窗口";    Integer number =NumberMachine.getInstance().getExpressManager().fetchServiceNumber();    System.out.println(windowName+"正在获取任务");    if(number != null){     System.out.println(windowName+"为第"+number+"个"+type+"客户服务");     long beginTime = System.currentTimeMillis();     //int maxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;     //long serviceTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;      try {       Thread.sleep(Constants.MIN_SERVICE_TIME);      } catch (InterruptedException e) {       e.printStackTrace();      }     long costTime = System.currentTimeMillis()-beginTime;     System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000+"秒");    }else{     System.out.println(windowName+"没有取到任务 ");     commonService();    }   }     private void vipService() {    String windowName = "第"+windowId+"号"+type+"窗口";    Integer number =NumberMachine.getInstance().getVipManager().fetchServiceNumber();    System.out.println(windowName+"正在获取任务");    if(number != null){     System.out.println(windowName+"为第"+number+"个"+type+"客户服务");     long beginTime = System.currentTimeMillis();     //int maxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;     //long serviceTime=new Random().nextInt(maxRand)+1+Constants.MIN_SERVICE_TIME;      try {       Thread.sleep(Constants.MIN_SERVICE_TIME);      } catch (InterruptedException e) {       e.printStackTrace();      }     long costTime = System.currentTimeMillis()-beginTime;     System.out.println(windowName+"为第"+number+"个"+type+"客户完成服务,耗时"+costTime/1000+"秒");    }else{     System.out.println(windowName+"没有取到任务");     commonService();    }   }}


(五)MainClass类
  1.用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
  2.接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
源码如下:

package com.isosoft.bank;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class MainClass {/**  * @author   */public static void main(String[] args) {  for(int i = 1;i<5;i++){   ServiceWindow commonWindow = new ServiceWindow();   commonWindow.setWindowId(i);   commonWindow.start();  }  ServiceWindow expressWindow = new ServiceWindow();  expressWindow.setType(CustomerType.EXPRESS);  expressWindow.start();    ServiceWindow vipWindow = new ServiceWindow();  vipWindow.setType(CustomerType.VIP);  vipWindow.start();    Executors.newScheduledThreadPool(1).scheduleAtFixedRate(     new Runnable(){      public void run(){       Integer number =NumberMachine.getInstance().getCommonManager().generateNewManager();/* 采用logger方式,无法看到直观的运行效果,因为logger.log方法内部并不是直接把内容打印出出来,而是交给内部的一个线程去处理,所以,打印出来的结果在时间顺序上看起来很混乱。*/         System.out.println("第"+number+"号普通客户等待服务!");      }     },     0,    Constants.COMMON_CUSTOMER_INTERVAL_TIME,     TimeUnit.SECONDS    );    Executors.newScheduledThreadPool(1).scheduleAtFixedRate(    new Runnable(){     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(){     public void run(){      Integer number =NumberMachine.getInstance().getVipManager().generateNewManager();      System.out.println("第"+number+"号VIP客户等待服务!");     }    },    0,   Constants.COMMON_CUSTOMER_INTERVAL_TIME*6,    TimeUnit.SECONDS   );}}


(六)Constants类
  1.定义三个常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME。
源码如下:

package com.isosoft.bank;

public class Constants {

/**
  * @author
  */

public static int MAX_SERVICE_TIME = 10000;
public static int MIN_SERVICE_TIME = 1000;

       /*每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来  

        平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以,   

           1秒钟产生一个普通客户比较合理,*/ 
public static int COMMON_CUSTOMER_INTERVAL_TIME=1;

}

------- android培训、java培训、期待与您交流! ----------详细请查看:http://edu.csdn.net

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 去哪儿网订机票时邮箱写错了怎么办 在南航航班上把手机丢飞机上怎么办 买了品牌鞋穿了一周就破了怎么办 狗让狠狠的打了一顿不理人了怎么办 调好米粉宝宝吃的时候就凉了怎么办 情人间闹分手删了微信后悔了怎么办 8个月宝宝不坐椅子一直要抱怎么办 2个月婴儿3天没有拉大便了怎么办 8个月的宝宝不吃米糊和稀饭怎么办 2岁零5个月的宝宝不说话怎么办 两岁宝宝不拔掉老是拉在裤上怎么办 一岁的宝宝吞了一颗五子棋该怎么办 别人欠我钱还把我拉黑我该怎么办 欠我钱的人耍赖不还我该怎么办 交易猫买的炉石传说号被找回怎么办 淘宝上卖水果过季了不想下架怎么办 两岁宝宝被蚊子咬了挠破流水怎么办 我打了人一拳他就躺地下了怎么办 在微信上被认识的人骗了钱该怎么办 微信上面被不认识的人骗了钱怎么办 柜体和订做的柜门颜色对不上怎么办 拉鞭炮的车压了我的电车不陪怎么办 脚爱出汗穿高跟凉鞋总往前滑怎么办 视频的格式是VⅠD打开很慢怎么办 汕头普法学法我点了考试没考怎么办 德云的生活攻略第三天卡关了怎么办 我的世界房子被参观的人烧了怎么办 新买的手表返厂维修弄划伤了怎么办 糖猫手表丢了别人捡了换了卡怎么办 我妈总怀疑我爸偷她东西怎么办啊 在百度上买的演出票不配送了怎么办 北交大预报名信息填错了怎么办保研 我租了个店面房子但是写了拆怎么办 电话换了微信账号密码都忘了怎么办 宝宝被开水烫了的泡泡破皮了怎么办 脚上泡泡破了的留下的黑印子怎么办 我的车子被前夫霸占了不给我怎么办 自己和同学吵了一架生气了要怎么办 旅游 徐州