一個基於文字介面的綜合練習,主要用於串聯和回憶知識點,比較簡單
=============房屋出租系統選單============
1 新 增 房 源
2 查 找 房 屋
3 刪除房屋資訊
4 修改房屋資訊
5 房 屋 列 表
6 退 出
請輸入你的選擇(1-6):
=============新增房屋============
姓名: jk
電話: 174
地址: 豐臺區
月租: 5600
狀態:
未出租
=============查詢房屋資訊============
請輸入想查詢的房屋ID:
1
1 jk1 13544856575 西青區 1800 未出租
=============刪除房屋資訊============
請輸入待刪除的房屋編號或輸入-1退出: 1
請輸入你的選擇(Y/N): 請小心選擇
y
=============刪除房屋資訊成功============
=============修改房屋資訊============
請選擇待修改房屋編號(-1退出):
2
姓名(jk):jack
電話(174):124
地址(豐臺區): 海淀區
租金(5600):5300
狀態(未出租):已出租
=============修改房屋資訊成功============
=============房屋列表============
編號 房主 電話 地址 月租 狀態(未出租/已出租)
2 jack 124 海淀區 5300 已出租
3 gg 485 昌平區 1800 已出租
=============房屋列表顯示完畢============
=============房屋出租系統選單============
1 新 增 房 源
2 查 找 房 屋
3 刪除房屋資訊
4 修改房屋資訊
5 房 屋 列 表
6 退 出
請輸入你的選擇(1-6):6
請輸入你的選擇(Y/N): 請小心選擇
y
========已退出========
相較之前的練習來說,這個程式體量已經達到小專案級別。因此,需要使用合理的方式進行規劃
使用分層模式對軟體各部分功能進行設計規劃
步驟:
1、明確系統有哪些類
2、確定類之間的關係
系統希望通過文字介面進行展示
那麼顯示介面需要一個類實現【HouseView.java】
顯示介面中的各項功能背後需要的業務邏輯程式碼應該單獨放在一個類中,即該類用於相應主介面類的各項服務【HouseService.java】
在系統中,對於各種資料的操作是通過房屋類間接進行的【House.java】,其中定義了一間房屋應該包含的屬性與方法
三大主類基本完成了,現在需要一個呼叫各物件的類作為程式的入口,即【HouseRentApp.java】
上述類的關係如圖所示
ps:Utility類作為工具類是提前預製的,無需糾結,主要負責判斷輸入是否合法等
專案結構如下
理清關係後,最開始肯定先寫介面嘛,即HouseView中定義一個顯示主選單的方法【mainMenu】
//顯示主選單
//仍然是用之前提到的do-while迴圈實現顯示,loop標誌位控制是否結束(退出系統)顯示
public void mainMenu(){
do{
System.out.println("=============房屋出租系統選單============");
System.out.println("\t\t\t1 新 增 房 源");
System.out.println("\t\t\t2 查 找 房 屋");
System.out.println("\t\t\t3 刪除房屋資訊");
System.out.println("\t\t\t4 修改房屋資訊");
System.out.println("\t\t\t5 房 屋 列 表");
System.out.println("\t\t\t6 退 出");
System.out.print("請輸入你的選擇(1-6):");
key = Utility.readChar();
switch (key) {//以下是選單中各功能的實現方法,剛開始沒寫完可以先用sout佔位
case '1':
addHouse();
break;
case '2':
findHouse();
break;
case '3':
delHouse();
break;
case '4':
update();
break;
case '5':
listHouses();
break;
case '6':
exit();
loop = false;
break;
}
}while (loop);
注意,介面類的方法只負責介面部分的功能,對於資料的相關操作需要在業務類定義
介面類只負責參照相關業務方法
/*
* //定義House[],儲存House物件
1.響應HouseView的呼叫
2.完成對房屋資訊的各種操作
* (增刪改查c[create]r[read]u[update]d[delete])*/
public class HouseService {
}
接下來實現對現有房屋的展示,即房屋列表的展示【listHouses()】
為什麼先實現這個功能呢?因為能夠展示房屋意味著我們需要完成對房屋類的定義,這是後面的功能也需要的
因此作為基礎部分,需要先做這個房屋列表功能
//編寫listHouses()顯示房屋列表
//其中使用業務類的方法,範例化並返回房屋物件House陣列
//因此需要先對House進行定義
public void listHouses(){
System.out.println("=============房屋列表============");
System.out.println("編號\t\t房主\t\t電話\t\t地址\t\t月租\t\t狀態(未出租/已出租)");
House[] houses = houseService.list();//返回所有房屋資訊,儲存在houses陣列中
for (int i = 0; i < houses.length; i++) {
if (houses[i] == null) {
break;
}
System.out.println(houses[i]);
}
System.out.println("=============房屋列表顯示完畢============");
}
list()需要返回系統用於存放房屋資訊的一個陣列,陣列元素為房屋物件
通過遍歷此陣列可以獲取所有房屋的資訊
/*
* //定義House[],儲存House物件
1.響應HouseView的呼叫
2.完成對房屋資訊的各種操作
* (增刪改查c[create]r[read]u[update]d[delete])*/
public class HouseService {
private House[] house;
//構造器
public HouseService(int size){
house = new House[size];//建立HouseService物件時,需要指定House陣列的大小
//測試,初始化一個預設HouseService物件
house[0] = new House(1, "jk", "13544856575","西青區", 1800,"未出租");
}
//list方法返回house(陣列)
public House[] list(){
return house;
}
}
這裡已經需要使用房屋類了,自然的我們需要編寫房屋類
房屋類House.java如下
/*
* House的物件表示一個房屋資訊*/
public class House {
//需要以下資訊
//編號 房主 電話 地址 月租 狀態(未出租/已出租)
private int id;
private String name;
private String phone;
private String address;
private int rent;
private String state;
public House(int id, String name, String phone, String address, int rent, String state) {
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
this.rent = rent;
this.state = state;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getRent() {
return rent;
}
public void setRent(int rent) {
this.rent = rent;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//為了方便的輸出物件資訊,需要實現toString方法
//比如有House h1,這樣直接sout(h1)就可以列印房屋資訊了
@Override
public String toString() {
return id +
"\t" + name +
"\t" + phone +
"\t" + address +
"\t" + rent +
"\t" + state ;
}
}
實現房屋列表之後,實際上房屋類也完成了定義
那麼現在可以考慮實現房屋資訊的新增
每個房屋新增進來應該給一個編號,這是需要注意的,後續需要通過編號查詢
//編寫addHouse()接受輸入,建立House物件,呼叫add方法
//addHouse()僅負責在介面層面的新增,實際去操控House物件陣列完成新增的方法屬於具體的業務功能
//即add()方法應該在HouseService.java中定義,在HouseView.java的addHouse()呼叫,遵循之前的類關係圖設計
public void addHouse(){
System.out.println("=============新增房屋============");
System.out.print("姓名: ");
String name = Utility.readString(8);
System.out.print("電話: ");
String phone = Utility.readString(12);
System.out.print("地址: ");
String address = Utility.readString(16);
System.out.print("月租: ");
int rent = Utility.readInt();
System.out.println("狀態: ");
String state = Utility.readString(3);
//按照輸入資訊,建立一個新的House物件
//id是系統分配
House newHouse = new House(0, name, phone, address, rent, state);
if(houseService.add(newHouse)){
System.out.println("=============新增房屋成功============");
}else {
System.out.println("=============新增房屋失敗============");
}
}
需要在該業務方法中實現對房屋物件陣列的新增資料操作
並且需要實現對房屋資訊的自動編號
public class HouseService {
private House[] house;
private int houseNums = 1;//記錄當前有多少個房屋資訊
private int idCounter = 1;//記錄當前的id增長到的值
//構造器
public HouseService(int size){
house = new House[size];//建立HouseService物件時,需要指定House陣列的大小
//測試,初始化一個HouseService物件
house[0] = new House(1, "jk", "13544856575","西青區", 1800,"未出租");
}
//list方法返回house(陣列)
public House[] list(){
return house;
}
//add方法,新增新物件,返回boolean
//輸入引數是House物件
public boolean add(House newHouse){
//判斷是否還可以繼續新增(暫時不考慮陣列擴容問題)
if(houseNums == house.length){//若房屋資訊數量大於陣列長度則不能再加
System.out.println("陣列已滿,無法新增");
return false;
}
//陣列還沒滿的話把newHouse物件加入到陣列,同時房屋數量計數+1
// house[houseNums] = newHouse;
// houseNums ++;//新增一個房屋
//上述程式碼可以利用"後++"的特性整合
//houseNums++的值是執行一次之後才會自增的
//例如,當前houseNums為1,陣列設定為10,新增房屋資訊肯定是可以的
//因此,在陣列索引為1的地方加入newHouse,之後houseNums自增為2
house[houseNums++] = newHouse;//後++
//需要設計一個id自增長機制,然後更新newHouse的id
// idCounter ++;
// newHouse.setId(idCounter);
newHouse.setId(++idCounter);//前++,同理
return true;
}
}
增刪改查,那麼現在應該實現房屋資訊的刪除
這裡可以根據房屋資訊的編號進行刪除,也可以根據房屋的具體資訊,例如:地址、姓名、電話等
以房屋編號為例
//編寫delHouse() 接收輸入的id號
//與addHouse()類似,最終的刪除邏輯在業務類中實現,這邊只是呼叫相關方法
public void delHouse(){
System.out.println("=============刪除房屋資訊============");
System.out.print("請輸入待刪除的房屋編號或輸入-1退出: ");
int delId = Utility.readInt();//獲取一個輸入
if(delId == -1){
System.out.println("=============放棄刪除房屋資訊============");
return;
}
//該方法本身就有迴圈判斷邏輯,必須輸入Y/N才能退出
char choice = Utility.readConfirmSelection();
if(choice=='Y'){//真的刪除就呼叫業務方法
if(houseService.del(delId)){
System.out.println("=============刪除房屋資訊成功============");
}else {
System.out.println("=============房屋編號不存在,刪除失敗============");
}
}else {
System.out.println("=============放棄刪除房屋資訊============");
}
}
需要在該業務方法中,按房屋編號實現對房屋物件陣列元素的刪除操作
//del方法,刪除一個房屋資訊
public boolean del(int delId){
//應先找到刪除房屋的對應下標,房屋編號與下標不對應
int index = -1;
for (int i = 0; i < houseNums; i++) {
if(delId == house[i].getId()){
//要刪除的房屋(id),是陣列下標為i的元素
index = i;//記錄i
}
}
if(index == -1){//說明delId在陣列中不存在
return false;
}
//如果找到應該怎麼刪除?
//待刪除元素(使用下標確定)的後一個元素前移,覆蓋待刪除元素
//然後最後一位,置為null,重複上述操作
for (int i = index; i < houseNums - 1; i++) {
house[i] = house[i+1];
}
//置空最後一個元素
//"前--"表示直接取用houseNums減一後的值,詳見業務方法add()中對於"後++"的解釋
// house[houseNums - 1] = null;
// houseNums--;//少一個元素
house[--houseNums] = null;//把當前存在的房屋資訊的最後一個置空
return true;
}
"增刪改查"中的查詢,依舊是先在介面類中給出功能findHouse(),呼叫業務方法實現房屋查詢
//根據id查詢房屋(改進,通過地址查詢)
public void findHouse(){
System.out.println("=============查詢房屋資訊============");
System.out.println("請輸入想查詢的房屋ID: ");
int findId = Utility.readInt();
House houses = houseService.findById(findId);//返回所有房屋資訊,儲存在houses陣列中
if(houses ! = null){
System.out.println(houses);
}else {
System.out.println("無查詢結果,請輸入正確的房屋ID");
}
}
查詢的具體方式也是根據編號來,這樣比較簡單。後續更新可以加入按其他屬性查詢的功能(摸了)
//findById()方法,根據id查詢房屋,返回House物件或者null
public House findById(int findId){
//遍歷房屋陣列
for (int i = 0; i < houseNums; i++) {
if(findId == house[i].getId()){
return house[i];
}
}
return null;
}
更新房屋資訊其實也包含著查詢動作,先查出來才能更新,因此業務上不用寫新的方法,複用findById()即可
//根據id修改房屋資訊
//調findById就行,不用在HouseService中新增新業務功能
public void update(){
System.out.println("=============修改房屋資訊============");
System.out.println("請選擇待修改房屋編號(-1退出):");
int updateId = Utility.readInt();
if(updateId == -1){
System.out.println("=============已放棄修改============");
return;
}
//根據輸入的ID查詢物件
//因為這裡是參照物件,所以原陣列是會被同步改動的
House house = houseService.findById(updateId);
if(house==null){
System.out.println("=============房屋資訊不存在。。。=============");
return;
}
//若房屋存在
System.out.print("姓名("+house.getName()+"):");
String name = Utility.readString(10,"");//若使用者直接回車則預設""
if (!"".equals(name)) {//如果不是空的就用get方法修改
house.setName(name);
}
System.out.print("電話(" + house.getPhone() + "):");
String phone = Utility.readString(12, "");
if (!"".equals(phone)) {
house.setPhone(phone);
}
System.out.print("地址(" + house.getAddress() + "): ");
String address = Utility.readString(18, "");
if (!"".equals(address)) {
house.setAddress(address);
}
System.out.print("租金(" + house.getRent() + "):");
int rent = Utility.readInt(-1);
if (rent != -1) {
house.setRent(rent);
}
System.out.print("狀態(" + house.getState() + "):");
String state = Utility.readString(3, "");
if (!"".equals(state)) {
house.setState(state);
}
System.out.println("=============修改房屋資訊成功============");
}
實現方式有點質樸,其實還可以優化的,下次再說
彙總一些用到的程式設計技巧
在編寫稍大一點的程式時,需要將頁面和業務分離
物件陣列也可以初始化
刪除陣列中元素的技巧:覆蓋刪除【來著業務方法del()】
//待刪除元素(使用下標確定)的後一個元素前移,覆蓋待刪除元素
//然後最後一位,置為null,重複上述操作
for (int i = index; i < houseNums - 1; i++) {
house[i] = house[i+1];
}
"後++"對於精簡程式碼的實際應用【業務方法add()】
// house[houseNums] = newHouse;
// houseNums ++;//新增一個房屋
//上述程式碼可以利用"後++"的特性整合
//houseNums++的值是執行一次之後才會自增的
//例如,當前houseNums為1,陣列設定為10,新增房屋資訊肯定是可以的
//因此,在陣列索引為1的地方加入newHouse,之後houseNums自增為2
house[houseNums++] = newHouse;//後++
package com./.../.houserent.view;
import com./.../.houserent.domain.House;
import com./.../.houserent.service.HouseService;
import com./.../.houserent.utils.Utility;
/**
* 1.顯示介面
* 2.接收使用者的輸入
* 3.呼叫HouseService完成對房屋資訊的各種操作
*/
public class HouseView {
private boolean loop = true;//控制顯示選單
private char key = ' ';//接受使用者選擇
private HouseService houseService = new HouseService(10);//陣列大小10
//根據id修改房屋資訊
//調findById就行,不用在HouseService中新增新業務功能
public void update(){
System.out.println("=============修改房屋資訊============");
System.out.println("請選擇待修改房屋編號(-1退出):");
int updateId = Utility.readInt();
if(updateId == -1){
System.out.println("=============已放棄修改============");
return;
}
//根據輸入的ID查詢物件
//因為這裡是參照物件,所以原陣列是會被同步改動的
House house = houseService.findById(updateId);
if(house==null){
System.out.println("=============房屋資訊不存在。。。=============");
return;
}
//若房屋存在
System.out.print("姓名("+house.getName()+"):");
String name = Utility.readString(10,"");//若使用者直接回車則預設""
if (!"".equals(name)) {//如果不是空的就用get方法修改
house.setName(name);
}
System.out.print("電話(" + house.getPhone() + "):");
String phone = Utility.readString(12, "");
if (!"".equals(phone)) {
house.setPhone(phone);
}
System.out.print("地址(" + house.getAddress() + "): ");
String address = Utility.readString(18, "");
if (!"".equals(address)) {
house.setAddress(address);
}
System.out.print("租金(" + house.getRent() + "):");
int rent = Utility.readInt(-1);
if (rent != -1) {
house.setRent(rent);
}
System.out.print("狀態(" + house.getState() + "):");
String state = Utility.readString(3, "");
if (!"".equals(state)) {
house.setState(state);
}
System.out.println("=============修改房屋資訊成功============");
}
//根據id查詢房屋(改進,通過地址查詢)
public void findHouse(){
System.out.println("=============查詢房屋資訊============");
System.out.println("請輸入想查詢的房屋ID: ");
int findId = Utility.readInt();
House houses = houseService.findById(findId);//返回所有房屋資訊,儲存在houses陣列中
if(houses != null){
System.out.println(houses);
}else {
System.out.println("無查詢結果,請輸入正確的房屋ID");
}
}
//完成退出確認
public void exit() {
//這裡我們使用Utility提供方法,完成確認
char c = Utility.readConfirmSelection();
if (c == 'Y') {
loop = false;
}
}
//編寫delHouse() 接收輸入的id號
//與addHouse()類似,最終的刪除邏輯在業務類中實現,這邊只是呼叫相關方法
public void delHouse(){
System.out.println("=============刪除房屋資訊============");
System.out.print("請輸入待刪除的房屋編號或輸入-1退出: ");
int delId = Utility.readInt();
if(delId == -1){
System.out.println("=============放棄刪除房屋資訊============");
return;
}
//該方法本身就有迴圈判斷邏輯,必須輸入Y/N才能退出
char choice = Utility.readConfirmSelection();
if(choice=='Y'){//真的刪除
if(houseService.del(delId)){
System.out.println("=============刪除房屋資訊成功============");
}else {
System.out.println("=============房屋編號不存在,刪除失敗============");
}
}else {
System.out.println("=============放棄刪除房屋資訊============");
}
}
//編寫addHouse()接受輸入,建立House物件,呼叫add方法
//addHouse()僅負責在介面層面的新增,實際去操控House物件陣列完成新增的方法屬於具體的業務功能
//即add()方法應該在HouseService.java中定義,在HouseView.java的addHouse()呼叫,遵循之前的類關係圖設計
public void addHouse(){
System.out.println("=============新增房屋============");
System.out.print("姓名: ");
String name = Utility.readString(8);
System.out.print("電話: ");
String phone = Utility.readString(12);
System.out.print("地址: ");
String address = Utility.readString(16);
System.out.print("月租: ");
int rent = Utility.readInt();
System.out.println("狀態: ");
String state = Utility.readString(3);
//建立一個新的House物件
//id是系統分配
House newHouse = new House(0, name, phone, address, rent, state);
if(houseService.add(newHouse)){
System.out.println("=============新增房屋成功============");
}else {
System.out.println("=============新增房屋失敗============");
}
}
//編寫listHouses()顯示房屋列表
//其中範例化呼叫了房屋物件House,並使用了物件陣列
//因此需要先對House進行定義
public void listHouses(){
System.out.println("=============房屋列表============");
System.out.println("編號\t\t房主\t\t電話\t\t地址\t\t月租\t\t狀態(未出租/已出租)");
House[] houses = houseService.list();//返回所有房屋資訊,儲存在houses陣列中
for (int i = 0; i < houses.length; i++) {
if (houses[i] == null) {
break;
}
System.out.println(houses[i]);
}
System.out.println("=============房屋列表顯示完畢============");
}
//顯示主選單
//仍然是用之前提到的do-while迴圈實現顯示,loop標誌位控制是否結束(退出系統)顯示
public void mainMenu(){
do{
System.out.println("=============房屋出租系統選單============");
System.out.println("\t\t\t1 新 增 房 源");
System.out.println("\t\t\t2 查 找 房 屋");
System.out.println("\t\t\t3 刪除房屋資訊");
System.out.println("\t\t\t4 修改房屋資訊");
System.out.println("\t\t\t5 房 屋 列 表");
System.out.println("\t\t\t6 退 出");
System.out.print("請輸入你的選擇(1-6):");
key = Utility.readChar();
switch (key) {
case '1':
addHouse();
break;
case '2':
findHouse();
break;
case '3':
delHouse();
break;
case '4':
update();
break;
case '5':
listHouses();
break;
case '6':
exit();
loop = false;
break;
}
}while (loop);
}
}
package com./.../.houserent.service;
import com./.../.houserent.domain.House;
/*
* //定義House[],儲存House物件
1.響應HouseView的呼叫
2.完成對房屋資訊的各種操作
* (增刪改查c[create]r[read]u[update]d[delete])*/
public class HouseService {
private House[] house;
private int houseNums = 1;//記錄當前有多少個房屋資訊
private int idCounter = 1;//記錄當前的id增長到的值
//構造器
public HouseService(int size){
house = new House[size];//建立HouseService物件時,需要指定House陣列的大小
//測試,初始化一個HouseService物件
house[0] = new House(1, "jk", "13544856575","西青區", 1800,"未出租");
}
//list方法返回house(陣列)
public House[] list(){
return house;
}
//findById()方法,根據id查詢房屋,返回House物件或者null
public House findById(int findId){
//遍歷房屋陣列
for (int i = 0; i < houseNums; i++) {
if(findId == house[i].getId()){
return house[i];
}
}
return null;
}
//del方法,刪除一個房屋資訊
public boolean del(int delId){
//應先找到刪除房屋的對應下標,房屋編號與下標不對應
int index = -1;
for (int i = 0; i < houseNums; i++) {
if(delId == house[i].getId()){
//要刪除的房屋(id),是陣列下標為i的元素
index = i;//記錄i
}
}
if(index == -1){//說明delId在陣列中不存在
return false;
}
//如果找到應該怎麼刪除?
//待刪除的下標位置的元素的後一個元素前移,覆蓋待刪除元素
//然後最後一位,置為null,重複上述操作
for (int i = index; i < houseNums - 1; i++) {
house[i] = house[i+1];
}
//置空最後一個元素
// house[houseNums - 1] = null;
// houseNums--;//少一個元素
house[--houseNums] = null;//把當前存在的房屋資訊的最後一個置空
return true;
}
//add方法,新增新物件,返回boolean
public boolean add(House newHouse){
//判斷是否還可以繼續新增(暫時不考慮陣列擴容問題)
if(houseNums == house.length){//不能再加
System.out.println("陣列已滿,無法新增");
return false;
}
//把newHouse物件加入到陣列
// house[houseNums] = newHouse;
// houseNums ++;//新增一個房屋
//上述程式碼可以利用"後++"的特性整合
//houseNums++的值是執行一次之後才會自增的
//例如,當前houseNums為1,陣列設定為10,新增房屋資訊肯定是可以的
//因此,在陣列索引為1的地方加入newHouse,之後houseNums自增為2
house[houseNums++] = newHouse;//後++
//需要設計一個id自增長機制,然後更新newHouse的id
// idCounter ++;
// newHouse.setId(idCounter);
newHouse.setId(++idCounter);//前++
return true;
}
}
package com./.../.houserent.domain;
/*
* House的物件表示一個房屋資訊*/
public class House {
//編號 房主 電話 地址 月租 狀態(未出租/已出租)
private int id;
private String name;
private String phone;
private String address;
private int rent;
private String state;
public House(int id, String name, String phone, String address, int rent, String state) {
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
this.rent = rent;
this.state = state;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getRent() {
return rent;
}
public void setRent(int rent) {
this.rent = rent;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
//為了方便的輸出物件資訊,需要實現toString方法
//比如有House h1,這樣直接sout(h1)就可以列印房屋資訊了
@Override
public String toString() {
return id +
"\t" + name +
"\t" +phone +
"\t" + address +
"\t" + rent +
"\t" + state ;
}
}
package com./.../.houserent;
import com./.../.houserent.view.HouseView;
public class HouseRentApp {
public static void main(String[] args) {
//建立HouseView物件,顯示介面,是程式的主入口
new HouseView().mainMenu();
System.out.println("========已退出========");
}
}