黑马程序员--银行业务调度系统学习

 

本例学习总结:本案例中用到了单例设计模式,要明白客户号与窗口叫号的产生方法,明白其中的逻辑关系。面向对象方法的运用,比如,窗口有类型属性是普通还是快速还是vip,有号这个属性,窗口是几号窗口,针对不同窗口再设计该窗口的处理方法,这样逻辑就清楚了。

需求分析:1.银行有三种业务窗口,分别为普通,快速,vip窗口,分别班里对应客户的业务,但是,快速和vip窗口可以办理普通客户业务。2,有三种类型客户,普通,快速,vip客户。3,模拟客户出现的概率比为6:3:1。4,普通和vip客户办理业务时间用随机数表示,快速客户业务办理时间用最小时间表示。

设计实现:三种类型客户办理业务时要有客户号,需要生成三种客户号,三种类型客户号有一个出客户号机器产生,所以,先设计一个产生客户号的类

 

import java.util.ArrayList;
import java.util.List;

public class NumberManager {
	private int lastNumber = 1;
	//为了取出排队号码方便,采用ArrayList
	private List<Integer> queueNumber = new ArrayList<Integer>();
	//由于取出和产生号码共享数据,要考虑同步问题,如果函数返回类型为int,由于在判断取出的号码是否为空,返回null时会出错,
	//所以用Integer作为返回类型,使用java的自动装箱特性
	public synchronized Integer generateNewNumber() {
		queueNumber.add(lastNumber);
		return lastNumber++;
	}
	public synchronized Integer fetchNumber() {
		if (queueNumber.size() > 0) {
			return queueNumber.remove(0);
		}
		else {
			return null;
		}
	}
}

然后,对于三种类型客户,设计一个类,管理产生的客户号如下:

public class NumberMachine {
	/*
	 * 单例设计模式
	 */
	private NumberMachine(){}
	private static NumberMachine instance = new NumberMachine();
	public static NumberMachine getInstance() {
		return instance;
	}
	
	private NumberManager commonManager = new NumberManager();
	private NumberManager expressManager = new NumberManager();
	private NumberManager vipManager = new NumberManager();
	
	public NumberManager getCommonManager() {
		return commonManager;
	}
	public NumberManager getExpressManager() {
		return expressManager;
	}
	public NumberManager getVipManager() {
		return vipManager;
	}
	
	
}

用到了单例设计模式,这是考虑到三种类型客户号有一个客户号机产生。

然后设计办理客户业务的窗口类,有属性:窗口类型和窗口号,在start方法中完成业务办理,分三种类型处理

import java.util.Random;
import java.util.concurrent.Executors;

public class ServiceWindow {

	private int number = 1;
	private CustomerType type = CustomerType.COMMON;
	
	public void setNumber(int number) {
		this.number = number;
	}
	public void setType(CustomerType type) {
		this.type = type;
	}
	public CustomerType getType() {
		return type;
	}
	
	public void start() {
		Executors.newSingleThreadExecutor().execute(new Runnable() {
			
			@Override
			public void run() {
				while (true) {
					switch (type) {
					case COMMON:
						commonService();
						break;
					case EXPRESS:
						expressService();
						break;
					case VIP:
						vipService();
						break;
					
					}
				}
			}
		});
	}

以普通业务办理为例:下面是commonService()方法的代码:

private void commonService() {
		String windowName = "第" + number +"号" + type + "窗口";
		System.out.println(windowName + "开始获取普通任务");
		//获取客户服务号
		Integer serviceNumber = NumberMachine.getInstance().getCommonManager().fetchNumber();
		//如果服务号不为空就办理业务
		if (serviceNumber != null) {
			System.out.println(windowName + "开始为第"  + serviceNumber + "号客户服务");
			//设计一个在最大值和最新值之间的随机数模拟业务办理时间
			int maxRand = Constants.MAX_SEVICE_TIME - Constants.MIN_SEVICE_TIME;
			int serviceTime = new Random().nextInt(maxRand) + 1 + Constants.MIN_SEVICE_TIME;
			try {
				Thread.sleep(serviceTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(windowName + "完成为第" + serviceNumber + "号普通客户服务,总共耗时" + serviceTime/1000 + "秒");		
		}else {
			System.out.println(windowName + "没有取到普通任务,将要空闲一秒");		
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}	
		}
	}

最后完成测试用例类:

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class Main{

	public static void main(String[] args) {
		//产生4个普通窗口
		for(int i=1;i<5;i++){
			ServiceWindow window =  new ServiceWindow();
			window.setNumber(i);
			window.start();
		}
	
		//产生1个快速窗口
		ServiceWindow expressWindow =  new ServiceWindow();
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();
		
		//产生1个VIP窗口		
		ServiceWindow vipWindow =  new ServiceWindow();
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();		
		
		//普通客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getCommonManager().generateNewNumber();
						System.out.println("第" + serviceNumber + "号普通客户正在等待服务!");						
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME, 
				TimeUnit.SECONDS);
		
		//快速客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getExpressManager().generateNewNumber();
						System.out.println("第" + serviceNumber + "号快速客户正在等待服务!");
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2, 
				TimeUnit.SECONDS);
		
		//VIP客户拿号
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						Integer serviceNumber = NumberMachine.getInstance().getVipManager().generateNewNumber();
						System.out.println("第" + serviceNumber + "号VIP客户正在等待服务!");
					}
				},
				0,
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 
				TimeUnit.SECONDS);
	}

}


其中COMMON_CUSTOMER_INTERVAL_TIME值是1,表明一个普通客户在一秒后出现一个,所以快速客户和vip客户出现的时间就是COMMON_CUSTOMER_INTERVAL_TIME*2和COMMON_CUSTOMER_INTERVAL_TIME*6.

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值