寫文本比敲代碼難多了?。,。?/p>
在我公布了要和“方方土的堃”進行項目合作之后,,本以為只要老老實實按照書本的項目一步一步研發(fā)就可以了,,但是沒想到我的合作伙伴把需求改成運行在命令行上的系統(tǒng)原型即可,本來我們決定在代碼中不要連數(shù)據(jù)庫,,但是等我把幾個存儲類寫得差不多的時候呢,,方方土的堃 就開始用上 SQL server 了。代碼寫了一半我也不太好改,,于是,,我打算把剩余部分寫完就結(jié)束該項目了,接下來的日子就好好專心學(xué)習(xí)了,。
我的架構(gòu)是按照MVC模式設(shè)計的,,其中 Database 類本來可以直接與數(shù)據(jù)庫相連,然后寫相應(yīng)的業(yè)務(wù)SQL查詢就好了,,而我自己手寫了一個,,但是個bug重發(fā)區(qū),曾經(jīng)費了不少時間去調(diào)試,。其次,,Core類只是對當(dāng)作程序的入口而用,承擔(dān) Database 與 UI 連接的工作統(tǒng)統(tǒng)寫在 Process 類里,, 這個類負(fù)責(zé)邏輯處理,。 UI 類則針對每一個用戶可能遇到的每一個Page都寫了一個方法,然后交由 Process 調(diào)用,,顯示窗口,。未來有時間的話,可以考慮將UI類改寫成 GUI ,。
該酒店管理系統(tǒng)現(xiàn)已實現(xiàn)的功能有:
用戶登陸
用戶權(quán)限控制
前臺開單
智能結(jié)帳
修改菜單
前后臺交換下單信息
智能結(jié)帳
生成日匯報賬單
IO
IO 類只是包括了從命令行獲取輸入的方法和將類序列化與分序列化的方法,,其中方法 getInput
,、getNum
,、getInt
都是通過 Scanner 類來獲取字符串、浮點數(shù)、整數(shù),, writeData
,、readData
則是通過 ObjectInputStream 和 ObjectOutPutStream 來實現(xiàn)序列化和反序列化。
IO 類里所有的方法都是 static 的,,即類方法,。
Database
首先,我先確定好數(shù)據(jù)模型,,并設(shè)計出如下數(shù)據(jù)表:
1. 菜單表(菜名,, 價格, 是否可供應(yīng))
1. 下單表(訂單號,, 桌號,, 訂單時間, 訂單金額,, 訂單菜名列別,, 剩余未上菜列表)
1. 日結(jié)帳表(日期, 金額)
1. 用戶表(員工好,, 員工民,, 登陸密碼, 權(quán)限角色)
1. 權(quán)限表(權(quán)限角色名, 授權(quán)列表)
把這些表每一行數(shù)據(jù)項用一個類去寫,,然后再以各表主碼為key,其類實例為value的hashmp作為 Database 的屬性,,通過這種方式將不同數(shù)據(jù)聚合于 Database 類。比如說以菜單表為例子,, Database 的結(jié)構(gòu)將會像這樣子的,。
public class Database implements Serializable { ? ?private Hashmap<String, Dish> dishTable = new ?Hashmap<String, Dish>();//菜名是字符串
? ?//...其他表
? ?//...具體業(yè)務(wù)方法}class Dish implements Serializable { ? ?float price; ? ?boolean isAvailable;
}
然后 Database 的方法與具體某項業(yè)務(wù)有關(guān),為了省時間,,則不做抽象,,每一個方法實現(xiàn)業(yè)務(wù)的目標(biāo)就好了。
為了持久化,, Database 及數(shù)據(jù)項類都應(yīng)用了 Serializable 接口,。而 Database 的序列化和反序列化將由 Process 類調(diào)用 IO 方法執(zhí)行。
Core/Process
首先,, Core 類只是對程序的初始化而已,,具體代碼像這樣:
public class Core { ? ?public static void main(String[] args) {
? ? ? ?Process app = new Process();
? ? ? ?UI ui = new UI();
? ? ? ?IO io = new IO();//初始化以免發(fā)生某些錯誤
? ? ? ?app.start();
? ?}
}
Process 就是程序主體,在程序一開始,,則需要加載判斷數(shù)據(jù)庫文件是否存在,,以決定是執(zhí)行登陸還是重新注冊。于是 start 方法可以這么寫:
class Process {
? ?Database database; ? ?//...其他類成員變量
? ?public void exit() { ? ? ? ? ? ? ? ?//程序結(jié)束時保存數(shù)據(jù)庫
? ? ? ?IO.writeData(database, fileDir);
? ? ? ?System.exit(0);
? ?} ? ?public void start() {
? ? ? ?UI.welcomePage(); ? ? ? ? ? ? ? //歡迎頁
? ? ? ?if (IO.isFileExists(fileDir)) { //判斷指定路徑的數(shù)據(jù)庫文件是否存在
? ? ? ? ? ?database = (Database) IO.readData(fileDir);
? ? ? ? ? ?login();
? ? ? ?} else {
? ? ? ? ? ?DBAregister(); ? ? ? ? ? ? ?//重新安裝,,注冊管理員
? ? ? ?}
? ? ? ?on(); ? ? ? ? ? ? ? ? ? ? ? ? ? //進入菜單,,選擇具體動作
? ?}
}
Process 還實現(xiàn)了權(quán)限控制,。首先應(yīng)該知道 Process.on
的結(jié)構(gòu)是這樣子的:
class Process { ? ?public void on() { ? ? ? ?while(true) { ? ? ? ? ? ?int choice = ?UI.mainMenuPage(rolePermission); ?//UI展示菜單頁
? ? ? ? ? ?switch (choice) { ? ? ? ? ? ? ? ?case 0:
? ? ? ? ? ? ? ? ? ?exit();break; ? ? ? ? ? ? ? ?//...case n 分別對應(yīng)一次具體業(yè)務(wù)動作
? ? ? ? ? ? ? ?default: ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ?}
? ? ? ?}
? ?}
}
其中關(guān)鍵是數(shù)組 rolePermission
,具體思路是用戶在登錄時會得到自己的權(quán)限角色,,然后通過查詢數(shù)據(jù)庫的權(quán)限表,,將獲得的許可數(shù)組賦值到 ArrayList<Integer> Process.rolePermission
,在 UI 菜單展示頁則會根據(jù) rolePermission 里涉及的選項讓用戶選擇 rolePermission 的 index,, 然后 return rolePermission.get(index);
便實現(xiàn)權(quán)限的控制了,。【即你能選到的只可能是 rolePermission 里對應(yīng)的case】
UI
UI 類的設(shè)計反而是最簡單的,,因為在這個類你只需要考慮你想看到什么,,然后處理用戶輸入的步驟以及反饋就好了,所以可以先寫一些小的組件比如說 titleShow()
, inputTip()
等等,,再對應(yīng)與 Process 的具體業(yè)務(wù)組合成一個個 xxxxxPage()
,,比如說 welcomePage
、mainMenuPage
等,。 UI 類所有方法也都是 static 修飾的,。
有一點想要提一下的是,在我編程編到后面的時候,,突然覺得 Database 方法以及 UI方法 的接口并不是一致的,,然后我相當(dāng)多的數(shù)據(jù)轉(zhuǎn)換都在 Process 里進行, 再加上出現(xiàn)類似新添菜式是,,需要 UI.addDishPage()
返回一個 String dishName
和 float price
,,而java并不像Python那樣支持多返回值,因此我專門設(shè)計了一個類 Data ,,它是用于 Database 和 UI 返回多個數(shù)據(jù)值使用,每次返回的時候,, new Data()
然后向相應(yīng)的成員進行賦值。
class Data { ? ?int intNum; ? ?float floatNum; ? ?//...其他出現(xiàn)的數(shù)據(jù)類型}
上面就是我對此次項目的一個總結(jié),,如果大家有什么看法,,歡迎通過公眾號或者github提交issue的方式進行交流。
項目的github地址: https://github.com/SunKingSuper/myProject/tree/master/hsm