黑馬程序員 Java之實戰——銀行管理系統

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

 

 模擬實現銀行業務調度系統邏輯,具體需求如下:


1. 銀行內有6個業務窗口,1 - 4號窗口爲普通窗口,5號窗口爲快速窗口,6號窗口爲VIP窗口。

2.有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶(辦理如交水電費、電話費之類業務的客戶)。

3.異步隨機生成各種類型的客戶,生成各類型用戶的概率比例爲:

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

4.客戶辦理業務所需時間有最大值和最小值,在該範圍內隨機設定每個VIP客戶以及普通客戶辦理業務所需的時間,

快速客戶辦理業務所需時間爲最小值(提示:辦理業務的過程可通過線程Sleep的方式模擬)。

5.各類型客戶在其對應窗口按順序依次辦理業務。

6.當VIP(6號)窗口和快速業務(5號)窗口沒有客戶等待辦理業務的時候,這兩個窗口可以處理普通客戶的業務,而一旦有對應的客戶等待辦理業務的時候,則優先處理對應客戶的業務。

7.隨機生成客戶時間間隔以及業務辦理時間最大值和最小值自定,可以設置。

8.不要求實現GUI,只考慮系統邏輯實現,可通過Log方式展現程序運行結果。



問題分析:

1. 有三種對應類型的客戶:VIP客戶,普通客戶,快速客戶 ,異步隨機生成各種類型的客戶,各類型客戶在其對應窗口按順序依次辦理業務 。

(1)首先,經常在銀行辦理業務的人更有利於理解本系統

(2)由於有三類客戶,每類客戶的號碼編排都是完全獨立的,所以,我想到本系統一共要產生三個號碼管理器對象,各自管理一類用戶的排隊號碼。

這三個號碼管理器對象統一由一個號碼機器進行管理,這個號碼機器在整個系統中始終只能有一個,所以,它要被設計成單例。

2. 各類型客戶在其對應窗口按順序依次辦理業務 ,準確地說,應該是窗口依次叫號。

(1)各個窗口怎麼知道該叫哪一個號了呢?它一定是問的相應的號碼管理器,即服務窗口每次找號碼管理器獲取當前要被服務的號碼。

(2)如果我不是多次親身經歷銀行的這種業務,再加之積累了大量面向對象的應用開發經驗,我也不知道能否輕鬆進行這種設計,能否發掘出其中隱含的對象信息,

我真說不出具體的經驗是什麼,就是日積月累出來的一種感覺。難道這就是傳說中的:“只可意會,不可言傳?”

綜上所述,我們可以得到以下結論

1、需要有一個號碼產生器類,該號碼產生器只能通過單例模式來產生,該號碼提供3個方法,分別可以生成3種不同類型的號碼

2、需要有一個號碼管理器類,它可以從號碼產生器中獲取號碼,也可以提供下一個需要服務的號碼

3、需要有一個服務窗口類,它可以從號碼管理器中獲取下一個需要服務的號碼,並且對3種不同的客戶進行服務

面向對象的關鍵:

你不能首先考慮這個程序需要實現什麼,你必須要首先思考這個程序要模擬什麼

也就是說,你必須要先通過在實際生活中的思維方式,把整個業務流程模擬出來

然後再對整個業務流程進行抽象

技術要點:
1、當你已經將一個系統的結構設計好之後,就應當從最簡單的一小段核心代碼寫起這段核心代碼可以不通用,可以只實現最基本的一個小功能,也可以寫的非常不完善但是,當你以後需要這段代碼提供更通用的功能時,你就只需要按照你的設計去逐漸擴充這段代碼就可以了其實最重要的就是,不要妄想從一開始你就把代碼寫的非常完美,編寫代碼的過程,永遠就是一個不斷完善已有代碼的過程
2、如果多個方法的代碼中只有部分邏輯不同,大部分都是相同的話,就可以把這些方法統一成一個方法然後,把這個方法中邏輯不同的部分抽取出來,定義成另外一個方法,然後爲其創建若干個子類並重寫抽取出來的這個方法這樣在不同的子類中調用同一個方法時,就可以實現不同的邏輯了
3、當需要使用多線程同時訪問一個對象時,需要使用synchronize來控制線程的安全

其中文件對於這種問題一定不要慌張,一定要仔細分析,並利用好網絡資源

其中有些是參考了一些老師的講解和代碼

實現的代碼

package com.isoftstone.interview.bank;

public class Constants {

 public static int MAX_SERVICE_TIME = 10000; 

 public static int MIN_SERVICE_TIME = 1000;

 public static int COMMON_CUSTOMER_INTERVAL_TIME = 1;  

}

//客戶的類型

package com.isoftstone.interview.bank;

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;

 }

}

package com.isoftstone.interview.bank;

import java.util.concurrent.Executors;

import java.util.concurrent.TimeUnit;

import java.util.logging.Logger;

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();

 

      System.out.println("第" + serviceNumber + "號普通客戶正在等待服務!");      

     }

    }

    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 + "號快速客戶正在等待服務!");

     }

    },

    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客戶正在等待服務!");

     }

    },

 

    Constants.COMMON_CUSTOMER_INTERVAL_TIME * 6, 

    TimeUnit.SECONDS);

 }

}

 

package com.isoftstone.interview.bank;

public class NumberMachine {

 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;

 }

 

 private NumberMachine(){}

 public static NumberMachine getInstance(){

  return instance;

 }

 

 private static NumberMachine instance = new NumberMachine();

}

//編寫表示號碼機器的類

package com.isoftstone.interview.bank;

import java.util.ArrayList;

import java.util.List;

public class NumberManager {

 

 private int lastNumber = 1;

 private List<Integer> queueNumber = new ArrayList<Integer>();

 public synchronized int generateNewManager(){

  queueNumber.add(lastNumber);

  return lastNumber++;

 }

 

 public synchronized int fetchServiceNumber(){

  return queueNumber.remove(0);

 }

}

//完成表示業務窗口的類的細節代碼

//服務窗口類

package com.isoftstone.interview.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(){

 //如果爲普通客戶,使用switch是因爲比if-else效率高,switch中接收的參數爲int類型和枚舉類型的 

     public void run(){

      while(true){

       switch(type){

        case COMMON://普通

         commonService();

         break;

        case EXPRESS://快速

         expressService();

         break;

        case VIP://VIP

         vipService();

         break;

       }

      }

     }

    }

  );

 }

 

 //type的返回值調用CustomerType類的toString方法  

 private void commonService(){

//type的返回值調用CustomerType類的toString方法  

  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();

  } 

 }

}

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

 

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