黑马程序员——银行业务调度系统

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



一丶分析与设计

一丶面向对象的分析与设计
1、每一个客户就是由银行的一个取号机器产生号码的方式来表示,所以,要有一个号码管理器对象,这样就可以随即生成号码,相当于客户

2、有VIP客户,普通客户,快速客户,每类客户的号码编排都是完全独立的,所以
	|--要有三个号码管理器对象,各自管理一类用户的排队号码,三个号码管理器对象统一由一个号码机器管理
		|--由于这个号码机器在整个系统中只能有一个,所以把它设计成单例
		
3、各类用户在其对应的窗口按顺序依次办理业务
	|--服务窗口每次找号码管理器获取当前要被服务的号码

4、关系图


5、NumberManager类

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

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

/*
 *号码发生器
 */
public class NumberManager
{
	private int lastNumber = 0;
	private List queueNumbers = new ArrayList();

	public synchronized Integer generateNewNumber()
	{
		queueNumbers.add(++lastNumber);
		return lastNumber;
	}

	public synchronized Integer fetchNumber()
	{
		if (queueNumbers.size() > 0)
		{
			return (Integer) queueNumbers.remove(0);
		}
		else
		{
			return null;
		}
	}
}

6、lNumberMachine类

三丶NumberMachine类
	|--定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器
		|--定义三个对应的方法来返回这三个NumberManager对象。
	|--将NumberMachine类设计成单例。
	
四丶ServiceWindow类
	|--定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。 
	|--定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。

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

package study_note_bank;/* *管理号码发生器 */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;}}



7、ServiceWindow类

四丶ServiceWindow类
	|--定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。 
	|--定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
package study_note_bank;

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

/*
 *服务窗口
 */
public class ServiceWindow
{
	private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");
	private CustomerType type = CustomerType.COMMON;
	private int number = 1;

	public CustomerType getType()
	{
		return type;
	}

	public void setType(CustomerType type)
	{
		this.type = type;
	}

	public void setNumber(int number)
	{
		this.number = number;
	}

	public void start()
	{
		Executors.newSingleThreadExecutor().execute(new Runnable()
		{
			public void run()
			{
				// 下面这种写法的运行效率低,最好是把while放在case下面
				while (true)
				{
					switch (type)
					{
					case COMMON:
						commonService();
						break;
					case EXPRESS:
						expressService();
						break;
					case VIP:
						vipService();
						break;
					}
				}
			}
		});
	}

	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 maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
			int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_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();
			}
		}
	}

	private void expressService()
	{
		Integer serviceNumber = NumberMachine.getInstance().getExpressManager().fetchNumber();
		String windowName = "第" + number + "号" + type + "窗口";
		System.out.println(windowName + "开始获取快速任务!");
		if (serviceNumber != null)
		{
			System.out.println(windowName + "开始为第" + serviceNumber + "号快速客户服务");
			int serviceTime = Constants.MIN_SERVICE_TIME;
			try
			{
				Thread.sleep(serviceTime);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			System.out.println(windowName + "完成为第" + serviceNumber + "号快速客户服务,总共耗时" + serviceTime / 1000 + "秒");
		}
		else
		{
			System.out.println(windowName + "没有取到快速任务!");
			commonService();
		}
	}

	private void vipService()
	{

		Integer serviceNumber = NumberMachine.getInstance().getVipManager().fetchNumber();
		String windowName = "第" + number + "号" + type + "窗口";
		System.out.println(windowName + "开始获取VIP任务!");
		if (serviceNumber != null)
		{
			System.out.println(windowName + "开始为第" + serviceNumber + "号VIP客户服务");
			int maxRandom = Constants.MAX_SERVICE_TIME - Constants.MIN_SERVICE_TIME;
			int serviceTime = new Random().nextInt(maxRandom) + 1 + Constants.MIN_SERVICE_TIME;
			try
			{
				Thread.sleep(serviceTime);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			System.out.println(windowName + "完成为第" + serviceNumber + "号VIP客户服务,总共耗时" + serviceTime / 1000 + "秒");
		}
		else
		{
			System.out.println(windowName + "没有取到VIP任务!");
			commonService();
		}
	}
}

8、CustomerType类

package study_note_bank;

/*
 *定义枚举
 *	|--系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
 *	|--重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。

 */
public enum CustomerType
{
	COMMON, EXPRESS, VIP;
	public String toString()
	{
		String name = null;
		switch (this)
		{
		case COMMON:
			name = "普通";
			break;
		case EXPRESS:
			name = "快速";
			break;
		case VIP:
			name = name();
			break;
		}
		return name;
	}
}

9、Constants类

package study_note_bank;

/*
 *常量类,定义三个常量
 */
public class Constants
{
	public static int MAX_SERVICE_TIME = 10000; // 10秒!
	public static int MIN_SERVICE_TIME = 1000; // 1秒!

	/*
	 * 每个普通窗口服务一个客户的平均时间为5秒,一共有4个这样的窗口,也就是说银行的所有普通窗口合起来
	 * 平均1.25秒内可以服务完一个普通客户,再加上快速窗口和VIP窗口也可以服务普通客户,所以, 1秒钟产生一个普通客户比较合理,
	 */
	public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
}

10、主函数

package study_note_bank;

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

/*
 *|--用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
 *|--接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
 */
public class MainClass
{

	private static Logger logger = Logger.getLogger("cn.itcast.bankqueue");

	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();
				// logger.info("第" + serviceNumber + "号普通客户正在等待服务!");
				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);
	}

}


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


                                                             详细请查看:http://edu.csdn.net/heima

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值