----------------------------------android培训、java培训、期待与您交流!------------------------------
有三种对应类型的客户:vip客户,普通客户,快速客户,异步随机产生各种类型的客户,个类型客户在其对应窗口按顺序一次办理业务。
首先,经常在银行办理业务的人更有利于理解本系统,每一个客户其实就是由银行的一个取号机器产生号码的方式表示的。所以,想到要
有一个号码管理器对象,让这个对象不断的产生号码,就等于随机产生了客户。
由于有三类客户,每类客户的号码编排都是完全独立的,本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码,
这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,他要被设计成单例。
各类型客户在其对应窗口按顺序一次办理业务,准确的说,应该是窗口一次叫号。
各个窗口怎么知道叫哪一个号呢?他一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码
张老师的话:如果我不是多次亲身经历银行的这种业务,再加之积累了大量的面向对象的应用开发经验,我也不知道能否轻松
进行这种设计,能否发掘其中隐含的对象信息,我真说不出具体的经验是什么,就是日积月累出来的一种感觉。难道这就是传说中的
:“只可意会,不可言传”
NumberManager类
定义一个用户存储上一个客户号码的成员变量和用户存储所有等待服务的客户号码的队列集合。
定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行
同步。
NumberMachine类
定义三个成员变量分别指向三个NumberManager对象,分别表示普通,快速和vip客户的号码管理器,定义三个的方法来
返回这三个NumberManager对象。
将NumberManchine类设计成单例。
CustomerType枚举类 系统中有三种类型的客户,所以定义一个枚举类,其中定义三个成员分别表示三种类型的客户。 重写toString方法,返回类型的中文名称。这时在后面编码时重构出来的,刚开始不用考虑。 ServiceWindow类 定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法 定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。 mainClass类 用for循环创建出4个普通窗口,在创建1个快速窗口和一个vip窗口。 接着再创建三个定时器,分别定时去创建新的普通客户号码,新的快速客户号码,新的vip客户号码。 Constants类 定义三个常量:(时间范围)MAX_SERVICE_TIME,MIN_SERVICE_TIME,(产生普通用户的时间间隔,便于实现1:6:3的比例要求 通过产生时间间隔比例来实现) COMMON_CUSTOMER_INTERVAL_TIME
package cn.itcast.Bank; import java.util.ArrayList; import java.util.List; /* * 定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。 * 定义一个产生新号码的方法和获取马上要为之服务的号码的方法, * * 这两个方法被不同的线程操作了相同的数据,所以,要进行同步。 * */ public class NumberManager { //定义一个变量 上一次返回的号码 号码不可以是0 所以要从1开始 private int lastNumber = 1; //创建一个集合对象 private List<Integer> queueNumber=new ArrayList<Integer>();//面向接口编程 //产生一个整数 public synchronized Integer generateNewManager() { queueNumber.add(lastNumber); return lastNumber++; } //取要服务的号的方法 public synchronized Integer fetchServiceNumber(){ Integer number=null; if(queueNumber.size()>0){ number=queueNumber.remove(0); } return number; } }
package cn.itcast.Bank; /* * 管理三个号码的机器 * */ //三个管理器 public class NumberMachine { //普通客户管理器 private NumberManager commonManager = new NumberManager(); //快速客户管理器 private NumberManager expressManager = new NumberManager(); //vip客户管理器 private NumberManager vipManager = new NumberManager(); //获取普通管理器 public NumberManager getCommonManager() { return commonManager; } //获取快速管理器 public NumberManager getExpressManager() { return expressManager; } //获取vip管理器 public NumberManager getVipManager() { return vipManager; } // 单例 //私有化构造函数 private NumberMachine() {}; //通过这个方法返回类类型对象 public static NumberMachine getInstance() { return instance; } //创建类类型的对象 private static NumberMachine instance = new NumberMachine(); }
package cn.itcast.Bank; /* * 定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法 定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。 */ import java.util.Random; import java.util.concurrent.Executors; //服务的窗口 public class ServiceWindow { //枚举类 对象 = 枚举类 . 普通客户 private CustomerType type = CustomerType.COMMON; public void setType(CustomerType type) { this.type = type; } public void setWindowId(int windowId) { WindowId = windowId; } private int WindowId = 1; //开始 public void start() { //线程池 执行 newSingleThreadExecutor: 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程 Executors.newSingleThreadExecutor().execute(new Runnable() { //客户类型只有三个 。 //run方法内部就是不停的去取号码。 @Override public void run() { while (true) { switch (type) { //普通窗口 case COMMON: commonService(); break; //快速窗口 case EXPRESS: expressService(); break; //vip窗口 case VIP: vipService(); break; } } } }); } private void expressService() { //第几号什么类型的窗口 String windowName = "第" + WindowId + "号 " + type + "窗口"; System.out.println("正在获取任务"); // Integer number = NumberMachine.getInstance().getExpressManager() .fetchServiceNumber(); if (number != null) { System.out.println(windowName + "为" + number + "个" + type+"客户服务"); long beginTime = System.currentTimeMillis(); // int maxRand = Constants.MAX_SERVICE_TIME // - Constants.MIN_SERVICE_TIME; // long serveTime = 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("没有取到任务"); commonService(); } } private void commonService() { String windowName = "第" + WindowId + "号 " + type + "窗口"; System.out.println("正在获取任务"); Integer number = NumberMachine.getInstance().getCommonManager() .fetchServiceNumber(); if (number != null) { System.out.println(windowName + "为" + number + "个" + "普通客户服务"); //服务开始的毫秒值 long beginTime = System.currentTimeMillis(); //最大服务时间等于最大时间-最小的时间 int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; //产生的时间就是1000-10000 long serveTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME; try { Thread.sleep(serveTime); } catch (InterruptedException e) { e.printStackTrace(); } //耗费的时间 long costTime = System.currentTimeMillis() - beginTime; //某个窗口为某个号码服务耗时多少秒 System.out.println(windowName + "为" + number + "个" + "普通客户完成服务,耗时" + costTime / 1000 + "秒"); } else { System.out.println(windowName + "没有取到任务,先休息一秒"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } private void vipService() { String windowName = "第" + WindowId + "号 " + type + "窗口"; System.out.println("正在获取任务"); Integer number = NumberMachine.getInstance().getVipManager() .fetchServiceNumber(); if (number != null) { System.out.println(windowName + "为" + number + "个" + type+"客户服务"); long beginTime = System.currentTimeMillis(); int maxRand = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME; long serveTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SERVICE_TIME; try { Thread.sleep(serveTime); } catch (InterruptedException e) { e.printStackTrace(); } long costTime = System.currentTimeMillis() - beginTime; System.out.println(windowName + "为" + number + "个" + type + "客户完成服务,耗时" + costTime / 1000 + "秒"); } else { System.out.println(windowName + "没有取到任务"); commonService(); } } }
package cn.itcast.Bank; //定义一个枚举类。三种客户类型 普通,快速,vip public enum CustomerType { COMMON,EXPRESS,VIP; public String toString(){ switch (this){ case COMMON: return "普通"; case EXPRESS: return "快速"; case VIP: return name(); } return null; } }
package cn.itcast.Bank; /* * 定义三个常量:(时间范围)MAX_SERVICE_TIME,MIN_SERVICE_TIME,(产生普通用户的时间间隔,便于实现1:6:3的比例要求 * 通过产生时间间隔比例来实现) COMMON_CUSTOMER_INTERVAL_TIME */ public class Constants { //service:服务 //最大时间 public static int MAX_SERVICE_TIME=10000; //最小时间 public static int MIN_SERVICE_TIME=1000; public static int COMMON_CUSTOMER_INTERVAL_TIME=1; }
package cn.itcast.Bank; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * * @author Administrator * */ 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(CustomerType.VIP); vipWindow.start(); ServiceWindow expressWindow=new ServiceWindow(); expressWindow.setType(CustomerType.EXPRESS); expressWindow.start(); // Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ @Override public void run() { Integer serviceNumber=NumberMachine.getInstance().getCommonManager().generateNewManager(); System.out.println(serviceNumber+"号普通客户等待服务"); }}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME, TimeUnit.SECONDS); Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ @Override public void run() { Integer serviceNumber=NumberMachine.getInstance().getCommonManager().generateNewManager(); System.out.println(serviceNumber+"号快速客户在等待服务"); }}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME*6, TimeUnit.SECONDS); Executors.newScheduledThreadPool(1).scheduleAtFixedRate( new Runnable(){ @Override public void run() { Integer serviceNumber=NumberMachine.getInstance().getCommonManager().generateNewManager(); System.out.println(serviceNumber+"号vip客户在等待服务"); }}, 0, Constants.COMMON_CUSTOMER_INTERVAL_TIME*3, TimeUnit.SECONDS); } }
----------------------------------android培训、java培训、期待与您交流!------------------------------