黑馬程序員_【總結】_ Pa_銀行業務調度系統

銀行業務調度系統


---------- android培訓 java培訓 、期待與您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------
銀行系統


個人分析案例的思路就是,把可能是對象的都拿出來分析一下,看誰具有特殊數據提供什麼方法:
比如這個項目中,涉及到:
人、取號機、窗口
人:就是客戶,來銀行就是辦業務,但是業務是窗口(銀行)提供的


取號機分:提供    個人、vip、快速  三種排隊方式,說明其具備 爲3種方式排隊的功能。


窗口分:普通窗口1-4個、vip 1個、快速1個 提供客戶辦理的業務功能


OK ,人要排隊,就得去取號機取票:也就是說,取號機生成的號碼,等同於客戶,也就是說,人不是關鍵對象
取號機生成不同的號碼,號碼存放到一個集合中,號碼等待,
顯然,這個時候,需要一個能保證唯一的 類來進行管理這三組取號機
【】設計一個單列模式來管理
【】三種客戶各是一組取號機,各有一個集合 也就是形成了三組   取號機,由一個管理機管理

窗口呼叫各種號碼,側等同於把集合中第一個號碼移除
新增客戶,就是給集合add元素。


【】窗口  需要呼叫號碼,取得對應客戶的服務  那麼內部就應該封裝着 對3種客戶的處理機制


【】Main new 出 4個普通窗口,1個vip 窗口 1個快速窗口  
啓動 3個定時器 對應三種客戶人羣的到來(開始生成號碼),開始頻率的工作

-----------------------
【1】

package com.isoftstone.interview.bank;
/**銀行排號系統-1-----  取號機
1、new號
2、窗口取號
*/

import java.util.*;
public class NumberManager {
	private int lastNumber = 1;
	private List<Integer> queneNumber = new ArrayList<Integer>();
	
	//1 取號 表示新來一個客戶
	public synchronized Integer generteNewNumber(){	
		queneNumber.add(lastNumber);		
		return lastNumber++;
	}
	
	//2 窗口叫號,那麼等待的號碼,應該在一個集合中,叫一個則移除一個
	public synchronized Integer fetchNumber(){
		Integer number = null;
		if(queneNumber.size()>0){
			return number = queneNumber.remove(0);
		}
		else{
			return number;
		}
	}
	//3 處理的是同一個數據,所以必須要同步
}
//NumberManager end


小結論:
1、單獨看着是一個取號的機器,具備2個功能,
1、給客戶排隊小票
2、給窗口提供排隊號
2、客戶手中的號,也就是集合中的號,和窗口拿出去的號,必須一直,也就是需要同步



【2】

package com.isoftstone.interview.bank;
/**銀行排號系統-2-----  號碼管理器
1、三組客戶--3組取號機
2、唯一性
*/

public class NumberMachine {
	//1 創建3個客戶號碼管理器
	private NumberManager CommonManager = new NumberManager();
	private NumberManager VIPManager = new NumberManager();
	private NumberManager ExpressManager = new NumberManager();
	//2 生成 get 方法
	public NumberManager getCommonManager() {
		return CommonManager;
	}
	public NumberManager getVIPManager() {
		return VIPManager;
	}
	public NumberManager getExpressManager() {
		return ExpressManager;
	}
	
	//3 【】 把本類設計爲單列。
	
	private NumberMachine(){}		
	private static  NumberMachine instance = new NumberMachine();
	public static NumberMachine getInstance(){
		return instance;
	}	//single  end	
}
//NumberMachine end


小結:
1、new出三組 取號機 對應三種客戶
1、生成 對應是取號方法
2、唯一性肯定就是單列模式了。
1、私有構造方法
2、覆蓋getInstance方法
3、私有對象,返回對象

【3】
package com.isoftstone.interview.bank;
/***銀行排號系統-3-----  窗口
1、對外只有一個方法
2、內部封裝了 3種客戶處理機制
	1、普通客戶處理機制
	2、快速
	3、VIP
3、3種機制雷同,當快速和VIP無客戶時,應調用普通客戶機制
4、進行客戶選擇時,使用 枚舉和switch 是估錯的組合
5、學會 把常量集中放置在一個類中
*/

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




public class ServiceWindow {
	//4-0、 定義一個類型,類型只有三種,>>建立枚舉類
	private CustomerType type = CustomerType.COMMON; 
	//6、定義窗口序列號、默認1
	private int windowId = 1;
	//7、爲4-0和6 生成 set 方法
	public void setType(CustomerType type) {
		this.type = type;
	}
	public void setWindowId(int windowId) {
		this.windowId = windowId;
	}
	//1、對外只有一個功能;統稱辦業務
	public void start(){
		//2、內部封裝好的線程
		Executors.newSingleThreadExecutor().execute(new Runnable(){
			public void run() {
				while(true){
					//3、這個時候是獲取普通客戶?VIP?快速?所以要定義一個類型
					switch(type){
						case COMMON:
							commonService();
							break;
						case EXPRESS:
							expressService();
							break;
						case VIP:
							vipService();
							break;
					}
					
				}
			}
		});
	}
	//20  可以把17-19 的代碼進行優化 最後來完成 
	// 17  把功能封裝成 方法。  --【普通客戶】
	private void commonService() {
		//8 展示 幾號窗口正在爲什麼客戶服務   
		//9 看  CustomerType 枚舉類
		String windowName = "第"+windowId+"號"+type+"窗口"+""+"";
		//5、展示 信息 應該顯示那個窗口第幾個窗口在獲取什麼樣的任務
		Integer number = NumberMachine.getInstance().getCommonManager().fetchNumber();
		System.out.println(windowName+"正在獲取任務");
		//4-1、對獲取到的服務號碼進行判斷,null表示還沒有等待客戶
		if(number != null){
			System.out.println(windowName+"正在爲"+number+"號"+"【普通客】服服務");
			long beginTime = System.currentTimeMillis();//開始記時
			//11、模擬服務--服務時間的區間
			//12、根據題目,設置一個常量的區間
			//13、創建   Constants 常量類
			//14、設定服務時間隨機爲 1-10秒之間(普通:1-10、快速:1  VIP:1-10)
			int MaxRand = Constants.MAX_SERVICE_TIME-Constants.MIN_SERVICE_TIME;
			long serveTime = new Random().nextInt(MaxRand)+1+Constants.MIN_SERVICE_TIME;//在1-10 秒之間
			try {
				Thread.sleep(serveTime);//15、睡眠時間,代表正在給客戶處理業務。
			} catch (InterruptedException e) {
				e.printStackTrace();
			}//模擬服務  end
			long costTime =    System.currentTimeMillis()-beginTime;//耗費時間
			//10、展示 那個窗口爲那個客戶完成服務 以及所耗時間 
			System.out.println(windowName+"爲"+number+"號"+"普通客戶完成服務耗時:"+(costTime)/1000+"秒");
		}
		else{
			System.out.println(windowName+"沒有取到服務任務...休息3秒");
			//16、如果沒有服務--睡眠3秒  表示 等待時間
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}//common  end
	
	// 18  把功能封裝成 方法。  --【快速客戶】
		private void expressService() {//18-1  更改爲: expressService
			String windowName = "第"+windowId+"號"+type+"窗口";
			Integer number = NumberMachine.getInstance().getExpressManager().fetchNumber();//18-2  更改爲:getExpressManager();
			System.out.println(windowName+"正在獲取任務");
			if(number != null){
				System.out.println(windowName+"正在爲"+number+"號【"+type+"客戶】服務");
				long beginTime = System.currentTimeMillis();
				try {
					Thread.sleep(Constants.MIN_SERVICE_TIME);//18-3  更改爲:最小值
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				long costTime =    System.currentTimeMillis()-beginTime;
				System.out.println(windowName+"爲"+number+"個"+type+"客戶完成服務耗時:"+(costTime)/1000+"秒");//18-4:type 對應當前窗口客戶
			}
			else{
				System.out.println(windowName+"沒有【"+type+"】客戶等待");
				//18-5【】  更改爲: 沒有當前窗口的服務時、 處理普通窗口的人物
				commonService();
			}
		}//common  end
		
		// 19  把功能封裝成 方法。  --【VIP客戶】
		private void vipService() {//19-1  更改爲: vipService()//getVIPManager()
			String windowName = "第"+windowId+"號"+type+"窗口";
			Integer number = NumberMachine.getInstance().getVIPManager().fetchNumber();//19-2  更改爲:getVIPManager()
			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 serveTime = new Random().nextInt(MaxRand)+1+Constants.MIN_SERVICE_TIME;//在1-10 秒之間
				try {
					Thread.sleep(serveTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				long costTime =    System.currentTimeMillis()-beginTime;
				System.out.println(windowName+"爲"+number+"號"+type+"客戶完成服務耗時:"+(costTime)/1000+"秒");//19-3:type 對應當前窗口客戶
			}
			else{
				System.out.println(windowName+"沒有【"+type+"】客戶等待");
				//19-4【】  更改爲: 沒有當前窗口的服務時、 處理普通窗口的人物
				commonService();
			}
		}//common  end
	
}
// ServiceWindow end


小結
1、固定範圍的東西,可以定義爲枚舉
2、常量應該集中到一個類中存貯
3、發現 new Random() 和Thread.sleep();  switch   時常組合在一起。

【4】

package com.isoftstone.interview.bank;
/**銀行排號系統-4-----  枚舉 三種客戶信息*/
public enum CustomerType {
	//9  【】 ServiceWindow 類中第9 步  覆蓋toString 返回中文信息
	COMMON,VIP,EXPRESS;	
	
	//1覆蓋toString 返回對應的中文   對應MainClass類
	public String toString(){
		switch(this){
			case COMMON:
				return "普通";
			case EXPRESS:
				return "快速";
			case VIP:
				return name();
		}
		return null;
	}
}
//CustomerType end


小結
1、枚舉可以通過 toString 返回枚舉對應的值
2、枚舉很強大,多多學習



【5】

package com.isoftstone.interview.bank;
/**銀行排號系統-5-----  常量信息*/
public class Constants {
	//13 【】ServiceWindow 類中第13步  設定常量
	//13-1最大時間   10s
	public static int MAX_SERVICE_TIME = 10000;
	//13-2最小時間  1s
	public static int MIN_SERVICE_TIME = 1000;
	//10 【】MainClass 類中 第10步,設定一個常量
	public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;
 }
 //Constants end


小結
1、常量通常都是大寫多個單詞用_分割開
2、常量一定是public 修飾的  必須是static  可以是 final 



【6】

package com.isoftstone.interview.bank;

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


/**銀行排號系統-6-----  Main */
public class MainClass {
	public static void main(String[] args) {
		//1、new出3種窗口
		//2、4個【普通窗口】
		for(int i=1;i<5;i++){
			//2-1 創建  普通窗口
			ServiceWindow commonWindow = new ServiceWindow();
			//2-2 設定窗口編號
			commonWindow.setWindowId(i);
			//2-3 啓動窗口
			commonWindow.start();
		}
		//3、new1個【快速窗口】
		ServiceWindow expressWindow = new ServiceWindow();
			//3-1 設定 窗口的類型  而不是窗口的編號  --該窗口只有1個
		expressWindow.setType(CustomerType.EXPRESS);
		expressWindow.start();
		
		//4、new1個【VIP窗口】
		ServiceWindow vipWindow = new ServiceWindow();
			//4-1 設定 窗口的類型  
		vipWindow.setType(CustomerType.VIP);
		vipWindow.start();
		//------------------------------
		//5 模擬3種客戶 來取號
		//6 創建三組     ---  線程池--     啓動一個定時器
			//7、common 【普通客戶】
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//11、來普通客人,也就是叫號
						Integer number = NumberMachine.getInstance().getCommonManager().generteNewNumber();
						System.out.println("第"+number+"號 普通客戶"+"等待服務");
					}
				}, 
				0, // 啓動時,就開始運營
					//1, // 間隔  1秒  啓動一次run 功能  產生1個普通客戶,客戶比例:6:3:1  6秒6個
				//10-1、使用常量來表示 生成客戶的比例
				Constants.COMMON_CUSTOMER_INTERVAL_TIME,
				TimeUnit.SECONDS   //  設定前2者的  尺量單位爲 秒。
				);//  common end
			//8、express 【快速客戶】
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//12、來快速客人,也就是叫號
						Integer number = NumberMachine.getInstance().getExpressManager().generteNewNumber();
						System.out.println("第"+number+"號 快速客戶"+"等待服務");
					}
				}, 
				0, // 啓動時,就開始運營
					//2, // 6秒  3個
				//10-2、使用常量來表示 生成客戶的比例
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 2,
				TimeUnit.SECONDS   //  設定前2者的  尺量單位爲 秒。
				);//  common end
			//9、vip 【VIP客戶】
		Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//13、來VIP客人,也就是叫號
						Integer number = NumberMachine.getInstance().getVIPManager().generteNewNumber();
						System.out.println("第"+number+"號 VIP客戶"+"等待服務");
					}
				}, 
				0, // 啓動時,就開始運營
					//6, // 6秒1個  完成 比例生成客戶
				//10-3、使用常量來表示 生成客戶的比例
				Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6,
				TimeUnit.SECONDS   //  設定前2者的  尺量單位爲 秒。
				);//  common end
		
	}//  13  main  end
}
// MainClass  end


小結:
1、通過 new 表示對象的個數
2、注意 普通窗口new出來是 setWindowId()
而VIP和快速    則是    setType()
3、啓動3組定時器 四個參數分別是:
1、定時器主要功能
2、定時器第一次啓動時間
3、定時器頻率時間
4、 2個時間的時間單位
5、TimeUnit 是一個枚舉,封裝的是時間單位
6、Executors.newScheduledThreadPool(1).scheduleAtFixedRate
創建一個只有1線程的定時器。
7、Executors 線程池很強大。多多學習
4、好像就寫完了。
5、測試
7、做代碼,真的是要多練,這個系統,第一次看完視頻,第二次試着不到50分鐘就做完了
但是調試就花了一個多小時
吃了飯,又繼續做,然後半小時搞定,沒有錯誤。
而且,人都是剛學的時候,記憶很好,能寫出來
過個三五天什麼的,就不行了,畢竟閱歷不夠,見識不多,敲的代碼太少了。


上圖:











---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培訓、 java培訓 、期待與您交流!----------


----------------------------------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章