# 加油站圈存機系統 對於加油卡而言,圈存是將`用戶賬戶`中已存入的資金劃轉到所持的加油卡上後方可使用。通俗一點的說法就是您在網點把錢存入主卡中,再分配到下麵的副卡,由於副卡都在使用車輛的駕駛員手中,需要在加油的時候在加油站讓加油站員工劃一下即可,就是所謂的圈存。 #### 圈存操作流程 如 ...
加油站圈存機系統
對於加油卡而言,圈存是將用戶賬戶
中已存入的資金劃轉到所持的加油卡上後方可使用。通俗一點的說法就是您在網點把錢存入主卡中,再分配到下麵的副卡,由於副卡都在使用車輛的駕駛員手中,需要在加油的時候在加油站讓加油站員工劃一下即可,就是所謂的圈存。
圈存操作流程
如下圖所示,圈存機圈存的主要流程就是:插卡→輸入密碼→按圈存→可選的小票操作→退卡。
模擬開發圈存系統設計梳理
概述
已經瞭解了圈存業務大致內容。現在使用Java基礎課程所學習的知識,模擬開發一下這個圈存系統的功能。因為是模擬開發,所以有些細節會相應的做些調整。
比如:
- 我們沒有圈存機,因此沒有具體的交互實物,對此我們的系統採用控制台展示和輸入的方式來模擬交互。
- 使用圈存機只要加油卡插入到機器後,卡號就會讀入機器,我們只需要輸入密碼就行了。我們沒有實體卡環節,哈哈哈,甚至圈存機都沒,故此卡號需要我們自己輸入的方式模擬插卡。
- 沒有實物卡,那賬號從哪裡來?對此我們給模擬的系統加入一個隱藏的管理功能。這個功能呢,就做成輸入的卡號是指定的一個系統管理卡號和密碼,我們就進入隱藏的管理模塊,進行卡片的管理。(當然這個卡號普通用戶是不知道,只有我們內部的工作人員才知道,密碼也是內部保密的喲)(這個管理,涉及到卡片的新增、查詢、充值等,刪除就不加了,假裝沒有這個功能,畢竟不是銀行卡系統,假裝沒這麼細微服務)。
對此,我們給系統設計兩個功能體系,一個是用戶的圈存查詢功能,一個是管理員的後臺核心管理功能。
流程設計
整體流程圖概覽如下:
【細節說明】:
- 沒有退卡鍵,沒法做到每個界面都要有一個退卡按鈕提示,中間個別環節加入即可。
- 系統持續對外服務,沒有結束,都是走到開始界面,提示輸入賬號(卡號)。
類設計
1、油卡的JavaBean
油卡需要的屬性的:卡號,用戶姓名 userName
,卡密碼,油卡餘額,積分,賬戶餘額
- 卡號
cardId
:卡號不能位空,長度9位的數值,首位不為0。 - 卡密碼
password
:需要驗證密碼長度,進行空值判斷,但此處不做過多限制,只需長度大於0就好了,以及管理員密碼可以自己直接設置,此處我直接設置為”1“。 - 油卡餘額
money
:油卡中可以用於加油的餘額。浮點類型 - 積分
integral
:使用油卡獲得的積分,由管理員進行充值,整型 - 賬戶餘額
wallet
:個人賬戶的餘額,是用來充值油卡餘額的錢,浮點型 - 並且提供空參,滿參,getter以及setter方法
2.圈存系統類設計
-
圈存系統需要的成員變數:指定的系統的賬號
sysCardId
和密碼sysPassword
,方便使用;當前登入的賬戶對象curUserCard
;存儲用戶卡信息的集合fuelCardList
-
圈存系統需要加入:控制台輸入對象用於交互,隨機數對象用於生成卡號。設置一個有參構造,參數是
duelCardList
,用於測試;同時設置一個無參構造,用於生成對象,方便調用。 -
涉及到的主要方法:
-
主頁面:用於提示用戶操作,輸入賬號密碼等
-
管理員功能界面:查詢所有卡片信息,新增油卡,賬戶餘額充值,積分充值。
-
用戶功能:圈存功能和查詢功能
-
3.測試類的設計
測試類只需要加入main方法,然後聲明圈存系統類的對象,通過該對象調用啟動方法,作為程式的入口。可以設計一個用戶對象,方便測試時使用,不用每次測試都登入管理員賬戶新增用戶。
系統的具體開發
1.加油卡FuelCard類
代碼如下:
package org.example;
public class FuelCard {
// 分析: 需要哪些屬性:
// id: 唯一性,卡號 (cardId)
private String cardId;
// 姓名 userName
private String userName;
// 密碼 password
private String password;
// 錢(油卡裡的金額) 帶小數 money (amount)
private double money;
// 積分 Integral (只用整數,1個積分1塊錢)
private int integral;
// 賬戶的金額(錢包的金額) wallet 帶小數
private double wallet;
public FuelCard() {
}
public FuelCard(String cardId, String userName, String password, double money, int integral, double wallet) {
this.cardId = cardId;
this.userName = userName;
this.password = password;
this.money = money;
this.integral = integral;
this.wallet = wallet;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public int getIntegral() {
return integral;
}
public void setIntegral(int integral) {
this.integral = integral;
}
public double getWallet() {
return wallet;
}
public void setWallet(double wallet) {
this.wallet = wallet;
}
}
2.主歡迎界面(系統的啟動方法)
啟動器需要啟動提示語,提示用戶輸入卡號。輸入卡號後,調用校驗卡號的方法,校驗卡號是否符合卡號要求,如長度是九位數,並且是否包含非法字元。
校驗成功後,驗證賬號類型,判斷賬號屬於管理員賬號還是用戶賬號。如果屬於管理員賬號則跳轉管理員登入界面,如果屬於用戶賬號則加入當前登入用戶的成員變數curUserCard
中,並跳轉用戶登入界面
start() 方法,代碼如下:
public void systemStart() {
while (true) {
// 啟動提示
System.out.println("請輸入你的卡號");
String cardId = sc.next();
// 卡號校驗-->長度,內容
if (!checkCardId(cardId)) {
System.out.println("卡號錯誤!請重新輸入您的卡號");
continue;
}
// 管理員賬號校驗
if (isSystemCardId(cardId)) {
// 系統模塊
goSystem();
} else {
// 普通用戶模塊
// 查找用戶卡號數據 --> 已存在cardId且不是管理員賬戶。判斷是否存在這張用戶卡
FuelCard userCard = getFuelCardByCardId(cardId);
// 找不到則提示
if (userCard == null) {
System.out.println("當前用戶不存在,請充值輸入!");
continue;
}
// 找到後加入當前登入賬號(成員變數)
curUserCard = userCard;
goUserSystem();
}
}
}
卡號校驗功能
卡號校驗功能,對輸入的卡號進行長度和內容的判斷,判斷卡號是否符合要求,返回true和false共外部調用
/**
* 卡號校驗
*/
private boolean checkCardId(String cardId) {
// 卡號校驗-->長度,內容
if (cardId == null) {
return false;
}
if (cardId.length() != 9) {
return false;
}
for (int i = 0; i < cardId.length(); i++) {
if (cardId.charAt(i) < '0' || cardId.charAt(i) > '9') {
return false;
}
}
return true;
}
}
管理員賬號校驗
驗證賬號密碼是否是管理員角色,代碼如下:
/**
* 管理員賬號校驗
*/
private boolean isSystemCardId(String cardId) {
return sysCardId.equals(cardId);
}
3.管理員系統處理
驗證為管理員賬號後進入管理員登入系統,進入後,提示管理員用戶輸入密碼,判斷密碼輸入是否正確,是否和設置的密碼相同,若密碼不同則重新輸入,並且限制輸入密碼的次數。密碼錯誤超過限制次數,返回開始頁面,提示用戶重新輸入賬號。密碼正確則進入管理員的操作頁面。
3.1管理員登入系統模塊
private void goSystem() {
System.out.println("====管理員系統模塊====");
// 密碼校驗(次數限制)三次
int count = 3;
for (int i = 0; i < count; i++) {
// 輸入密碼
System.out.println("請輸入密碼:");
String inputPassword = sc.next();
if (sysPassword.equals(inputPassword)) {
break;
} else {
System.out.println("密碼輸入錯誤,還剩" + (count - i - 1) + "次機會");
}
if (count == (i + 1)) {
return;
}
}
// 密碼正確,進入交互界面
sysWelcome();
}
3.2管理員系統歡迎界面
代碼如下:
/**
* 管理員系統歡迎界面
*/
private void sysWelcome() {
while (true) {
System.out.println("====歡迎進入加油卡圈存後臺管理系統====");
System.out.println("1. 查詢(按1鍵)");
System.out.println("2. 添加油卡(按2鍵)");
System.out.println("3. 積分充值(按3鍵)");
System.out.println("4. 錢包充值(按4鍵)");
System.out.println("按e鍵返回(不區分大小寫)");
String input = sc.next();
switch (input) {
case "1":
// 查詢:展示系統卡裡的所有信息,列印出來
listAllCard();
break;
case "2":
// 添加油卡
addCard();
break;
case "3":
// 積分充值
addIntegral();
break;
case "4":
// 錢包充值
addWallet();
break;
case "e":
case "E":
// 做個友好提示,然後就return結束方法
System.out.println("拜~");
return;// 後面就可以不用break,直接結束方法了
default:
System.out.println("輸入有誤,請重新輸入");
break;
}
}
}
進入管理員操作界面後,可以執行管理員操作,包括查看所有油卡信息,新增卡號,積分充值,錢包充值四個功能
3.3查看所有油卡信息
對存儲賬號信息的集合fuelCardList
進行判空,如果集合為空則提示管理員,暫無賬戶信息。否則遍歷集合,輸出相關賬戶信息,由於密碼屬於私人信息,不能輸出密碼信息。
展示賬戶內容代碼如下:
/**
* 展示賬戶內容
*/
private void listAllCard() {
// 列印用戶集合信息 fuelCards
if (fuelCardList == null || fuelCardList.isEmpty()) {
System.out.println("暫無賬戶信息數據,請添加後查詢");
}
for (int i = 0; i < fuelCardList.size(); i++) {
FuelCard fuelCard = fuelCardList.get(i);
System.out.println("卡號:" + fuelCard.getCardId());
System.out.println("用戶:" + fuelCard.getUserName());
System.out.println("卡餘額:" + fuelCard.getMoney());
System.out.println("錢包金額:" + fuelCard.getWallet());
System.out.println("積分:" + fuelCard.getIntegral());
System.out.println("------------------------------");
}
}
3.4新增卡號
新增卡號,創建油卡對象,填寫相關的用戶信息,包括用戶名,用戶密碼;用戶密碼需要輸入兩次,確認密碼,如果兩次密碼都相同,則通過,否則提示重新輸入;賬戶(電子錢包)金額,只能輸入大於0的金額。卡號調用生成卡號的方法生成,而油卡餘額和積分,此處為新增油卡,因此無需過多關註。
設置完對象的這些屬性後,將油卡對象添加到油卡對象集合中
代碼如下:
/**
* 添加新油卡信息
*/
private void addCard() {
// 新建油卡對象
FuelCard newCard = new FuelCard();
System.out.println("請輸入用戶名:");
String userName = sc.next();
newCard.setUserName(userName);
// 密碼校驗(確認密碼)
while (true) {
System.out.println("請輸入密碼:");
String password = sc.next();
System.out.println("請確認密碼:");
String comfirmPassword = sc.next();
if (password.equals(comfirmPassword)) {
newCard.setPassword(password);
break;
}
System.out.println("兩次密碼不相同,請重新輸入");
}
// 錢包金額
while (true) {
System.out.println("請輸入錢包金額:");
double money = sc.nextDouble();
if (money > 0) {
newCard.setWallet(money);
break;
}
System.out.println("輸入的金額必須大於 0,請重新輸入!");
}
// 積分 新卡沒有積分
// 餘額 新卡沒有
// 生成卡號
String cardId = createCardId();
newCard.setCardId(cardId);
// 添加到集合中
fuelCardList.add(newCard);
}
3.5生成卡號
生成的卡號,要求9位數,開頭不能為0,且唯一(用戶賬號和管理員賬戶也不能重覆)
/**
* 生成卡號
*/
public String createCardId() {
while (true) {
String newCardId = "";
// 第一次直接生成
newCardId += (r.nextInt(9) + 1);///首位不能為0
for (int i = 0; i < 8; i++) {
newCardId += (r.nextInt(10));
}
// [補充bug修複] 不能和系統賬號重覆,即使重覆的可能性很小
if (sysCardId.equals(newCardId)) {
continue;
}
// 生成後判斷是否唯一,存在就繼續生成,不存在則返回生成的id
FuelCard fuelCard = getFuelCardByCardId(newCardId);
if (fuelCard == null) {
return newCardId;
}
}
}
3.6根據卡號查找油卡對象
根據卡號查找油卡對象,存在則返回油卡對象,否則返回null。
這個方法在積分充值,錢包充值,用戶登錄都需要用到。就是根據油卡id查出集合中的油卡對象。外部調用方法根據是否為null進行相應的判斷。
根據卡號查找油卡對象代碼如下:
/**
* 根據cardId查找油卡對象
*/
private FuelCard getFuelCardByCardId(String cardId) {
if (cardId == null) {
return null;
}
for (int i = 0; i < fuelCardList.size(); i++) {
if (cardId.equals(fuelCardList.get(i).getCardId())) {
return fuelCardList.get(i);
}
}
return null;
}
3.7積分充值
積分充值,檢測油卡集合中是否存在油卡對象,如果沒有則退出充值方法,否則一直查找不到油卡對象導致方法無法退出(也可以通過增加退出按鈕,完成業務需求)。輸入需要充值的油卡id,調用getFuelCardByCardId
方法,根據油卡id找到油卡對象,若卡號不存在則提示重新輸入。否則對油卡對象的積分屬性做增加積分處理。並且對增加的積分進行校驗,積分需要大於零。
積分充值代碼如下:
private void addIntegral() {
// 驗證
if (fuelCardList == null || fuelCardList.isEmpty()) {
System.out.println("系統中沒有用戶,無法充值");
return;
}
while (true) {
// 1.界面提示
System.out.println("=======積分充值=======");
// 1.1.請輸入卡號 ---> 判斷卡號是否正確]
System.out.println("請輸入卡號:");
String cardId = sc.next();
FuelCard card = getFuelCardByCardId(cardId);
if (card == null) {
System.out.println("卡號輸入錯誤,請重新輸入!");
continue;
}
while (true) {
// 充值積分
System.out.println("請輸入充值的積分:");
int integral = sc.nextInt();
// 校驗積分 積分要大於0,和原來的積分相加
if (integral > 0) {
card.setIntegral(card.getIntegral() + integral);
System.out.println("充值成功,充值 " + integral + ",積分餘額為:" + card.getIntegral());
return;
}
System.out.println("輸入錯誤!請輸入大於0的積分!");
}
}
}
3.8錢包充值
錢包充值和積分充值處理方法類似,可以直接複製粘貼,註意修改有出入的地方
錢包充值,檢測油卡集合中是否存在油卡對象,如果沒有則退出充值方法,否則一直查找不到油卡對象導致方法無法退出。輸入需要充值的油卡id,根據油卡id找到油卡對象,若卡號不存在則提示重新輸入。否則對油卡對象的錢包(wallet)屬性做增加錢包餘額處理。並且對增加的金額進行校驗,積分需要大於零。
錢包充值代碼如下:
/**
* 錢包充值
*/
private void addWallet() {
// 驗證
if (fuelCardList == null || fuelCardList.isEmpty()) {
System.out.println("系統中沒有用戶,無法充值");
return;
}
while (true) {
// 1.界面提示
System.out.println("=======錢包充值=======");
// 1.1.請輸入卡號 ---> 判斷卡號是否正確
System.out.println("請輸入卡號:");
String cardId = sc.next();
FuelCard card = getFuelCardByCardId(cardId);
if (card == null) {
System.out.println("卡號輸入錯誤,請重新輸入!");
continue;
}
while (true) {
// 充值錢錢
System.out.println("請輸入充值的金額:");
double wallet = sc.nextDouble();
// 校驗金額 金額要大於0,和原來的金額相加
if (wallet > 0) {
card.setWallet(card.getWallet() + wallet);
System.out.println("充值成功,充值 " + wallet + ",餘額為:" + card.getWallet());
return;
}
System.out.println("輸入錯誤!請輸入大於0的金額!");
}
}
}
至此,管理員業務 完成
4.普通用戶系統處理
驗證為普通用戶賬號後進入普通用戶登入系統,進入後,提示普通用戶輸入密碼,判斷密碼輸入是否正確,是否和對象中設置的密碼相同,若密碼不同則重新輸入,並且限制輸入密碼的次數。密碼錯誤超過限制次數,返回開始頁面,提示用戶重新輸入賬號。密碼正確則進入普通用戶的操作頁面。
4.1普通用戶登入系統模塊
代碼如下:
/**
* 普通用戶模塊
*/
private void goUserSystem() {
System.out.println("====用戶系統模塊");
// 校驗密碼,限制三次
int count = 3;
for (int i = 1; i <= count; i++) {
System.out.println("請輸入你的密碼:");
String password = sc.next();
if (curUserCard.getPassword().equals(password)) {
break;
} else {
System.out.println("密碼輸入錯誤,還剩" + (count - i) + "次機會");
}
if (count == i) {
return;
}
}
// 成功後進入用戶的操作界面
userWelcome();
}
4.2用戶系統歡迎界面
/**
* 用戶歡迎界面(用戶操作界面)
*/
private void userWelcome() {
while (true) {
System.out.println("=====歡迎使用加油卡圈存系統=====");
System.out.println("1. 圈存(按1鍵)");
System.out.println("2. 查詢(按2鍵)");
System.out.println("按《退卡鍵》退卡(按e鍵)(不區分大小寫)");
String input = sc.next();
switch (input) {
case "1":
// 用戶圈存
userTransfer();
break;
case "2":
// 用戶查詢
userFind();
break;
case "e":
case "E":
// 做個友好提示,然後就return結束方法
System.out.println("拜~");
return;// 後面就可以不用break,直接結束方法了
default:
System.out.println("輸入有誤,請重新輸入");
break;
}
}
}
進入用戶操作界面後,可以執行用戶相關操作,包括用戶查詢和用戶圈存兩個功能
4.3用戶查詢方法
列印提示語句,讓用戶選擇查詢操作,退卡操作直接使用return關鍵字結束方法即可。
private void userFind() {
while (true) {
System.out.println("=====查詢=====");
System.out.println("1. 賬戶餘額查詢");
System.out.println("2. 積分查詢");
System.out.println("按《退卡鍵》退卡(按e鍵)(不區分大小寫)");
String input = sc.next();
switch (input) {
case "1":
// 錢包查詢
System.out.println("當前餘額為:" + curUserCard.getWallet());
break;
case "2":
// 積分查詢
System.out.println("當前賬戶積分為:" + curUserCard.getIntegral());
break;
case "e":
case "E":
// 做個友好提示,然後就return結束方法
System.out.println("拜~");
return;// 後面就可以不用break,直接結束方法了
default:
System.out.println("輸入有誤,請重新輸入");
break;
}
}
}
個人認為,根據流程圖寫的方法, 不如直接查詢全部信息,也符合正常業務流程並且代碼量相對較少。
代碼如下:
/**
* 用戶查詢
*/
private void userFind() {
// 不如直接查詢全部信息
System.out.println("=====查詢=====");
System.out.println("當前油卡餘額為:" + curUserCard.getMoney());
System.out.println("當前賬戶積分為:" + curUserCard.getIntegral());
System.out.println("當前賬戶餘額為:" + curUserCard.getWallet());
}
4.4用戶圈存
判斷用戶賬戶餘額是否大於0,小於等於0則無法進行圈存業務。
判斷結束後提示用戶操作,根據輸入的操作,執行。對輸入的金額(積分)進行判斷,只能輸入大於0的金額(積分);還要對輸入的金額(積分)是否小於賬戶餘額(積分)進行判斷,只有小於賬戶餘額(積分)才能進行圈存。圈存成功,減少賬戶餘額(積分),怎加油卡餘額,並提示圈存成功,返回操作界面
/**
* 用戶圈存
*/
private void userTransfer() {
// 判斷用戶賬戶餘額是否大於0,小於0則無法充值
if (curUserCard.getWallet() <= 0) {
return;
}
while (true) {
System.out.println("======= 請選擇圈存方式 =======");
System.out.println("1、積分圈存");
System.out.println("2、電子錢包圈存");
System.out.println("按e鍵返回(不區分大小寫)");
String op = sc.next();
switch (op) {
case "1":
System.out.println("當前積分餘額為:" + curUserCard.getIntegral());
if (curUserCard.getIntegral() <= 0) {
System.out.println("積分不足,無法圈存");
break;
}
//可以封裝成方法,選中,快捷鍵ctrl + alt + M
while (true) {
System.out.println("請輸入圈存金額:");
int money = sc.nextInt();
if (money <= 0) {
System.out.println("請輸入大於0的數!");
continue;
}
if (money > curUserCard.getIntegral()) {
System.out.println("輸入的金額大於積分,無法充值!");
continue;
}
curUserCard.setMoney(curUserCard.getMoney() + money);
curUserCard.setIntegral(curUserCard.getIntegral() - money);
System.out.println("圈存成功!當前餘額為:" + curUserCard.getMoney() + ",當前剩餘積分為:" + curUserCard.getIntegral());
return;
}
case "2":
System.out.println("當前賬戶餘額為:" + curUserCard.getWallet());
if (curUserCard.getWallet() <= 0) {
System.out.println("賬戶餘額不足,無法圈存");
}
while (true) {
System.out.println("請輸入圈存金額:");
int money = sc.nextInt();
if (money <= 0) {
System.out.println("請輸入大於0的數!");
continue;
}
if (money > curUserCard.getWallet()) {
System.out.println("輸入的金額大於賬戶餘額,無法充值!");
continue;
}
curUserCard.setMoney(curUserCard.getMoney() + money);
curUserCard.setWallet(curUserCard.getWallet() - money);
System.out.println("圈存成功!當前餘額為:" + curUserCard.getMoney() + ",當前賬戶餘額為:" + curUserCard.getWallet());
return;
}
case "e":
case "E":
// 做個友好提示,然後就return結束方法
System.out.println("拜~");
return;
default:
System.out.println("輸入有誤,請重新輸入");
break;
}
}
}
可以將積分圈存操作和賬戶餘額圈存操作封裝成方法,代碼會更加整潔。
至此加油卡圈存系統基本完成
測試類的編寫
public static void main( String[] args )
{
//為了方便測試可以先增加一個用戶進行測試
//ArrayList<FuelCard> testDate = new ArrayList<>();
//FuelCard fuelCard = new FuelCard("111222333","duoduo測試","2",20.0,1120,10000.0);
//testDate.add(fuelCard);
//FuelCardSys fuelCardSys = new FuelCardSys(testDate);
FuelCardSys fuelCardSys = new FuelCardSys();
fuelCardSys.systemStart();
}