一、房屋出租系统
![image]()
// 01HouseRentApp
package com.alice.houserent;
import com.alice.houserent.view.HouseView;
/*
创建一个HouseRentApp.java调用HouseView对象以显示主菜单
因为这个文件是运行整个项目的文件,也可以不用创建一个包来专门存放,直接放到主包下面
houserent
*/
public class HouseRentApp {
public static void main(String[] args) {
new HouseView().runMain();
}
}
// 02Utility
package com.alice.houserent.utils;
/*
创建一个工具类,完成获取用户的各种输入
还需要创建一个houserent.utils来存放工具
首先准备一个工具类,磨刀不误砍柴工
准备工具类Utility,提高开发效率
在实际开发中,公司都会提供相应的工具类和开发库,可以提高开发的效率,程序员也需要能够看懂别人写的代码
并且能够正确的调用
*/
/**
* 工具类的作用:
* 处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
*/
import java.util.*;
/**
*/
public class Utility {
//静态属性。。。
/*
在 Java 中,静态属性(Static Attributes),
也称为类变量(Class Variables),
是用 static 关键字修饰的成员变量。
它们与类本身关联,而不是类的实例(对象)。
1. 共享数据(Shared Across Instances)
静态属性被所有类的实例共享,修改它的值会影响所有对象。
适用场景:统计对象数量、配置参数等需要全局共享的数据。
2. 节省内存(Memory Efficiency)
静态属性在类加载时初始化,存储在方法区(Method Area),而非堆内存(Heap)。
无论创建多少对象,静态属性只存一份,避免重复占用内存。
3. 通过类名直接访问(No Instance Needed)
静态属性可以通过类名.属性名直接访问,无需创建对象。
适用场景:工具类的常量或共享资源(如Math.PI)。
还有其他,这里我没有写
*/
private static Scanner scanner = new Scanner(System.in);
/**
* 功能:读取键盘输入的一个菜单选项,值:1——5的范围
* @return 1——5
* 这里太局限了,应该可以确定范围的
* int num = 5; // 输入的数字(0~9)
* char charNum = (char) (num + '0'); // 转换为字符 '5'
* System.out.println(charNum); // 输出: 5
* 利用偏移量以确定菜单编号
*/
public static char readMenuSelection(int menuMaxId) {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);//包含一个字符的字符串
c = str.charAt(0);//将字符串转换成字符char类型
// if (c != '1' && c != '2' &&
// c != '3' && c != '4' && c != '5') {
// System.out.print("选择错误,请重新输入:");
// } 这个地方感觉老韩写的有点复杂,像下面这样写就好
if (c < '1' || c > (char)(menuMaxId + '0')) {
// 检查 ASCII 值是否在 '1'~'5' 范围,这里的5应该可以自定义长度,这个位置我使用偏移量来做
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
* 功能:读取键盘输入的一个字符
* @return 一个字符
*/
public static char readChar() {
// String str = readKeyBoard(1, false);//就是一个字符
// return str.charAt(0);
// 这里一行代码就行了,有点啰嗦
return readKeyBoard(1, false).charAt(0);
}
/**
* 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
* @param defaultValue 指定的默认值
* @return 默认值或输入的字符
*/
public static char readChar(char defaultValue) {
String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
return (str.length() == 0) ? defaultValue : str.charAt(0);
}
/**
* 功能:读取键盘输入的整型,长度小于2位
* 这里更改一下
* @return 整数
*/
public static int readInt() {
int n;
for (; ; ) {
String str = readKeyBoard(6, false);//一个整数,长度<=2位,这边更改了
try {
n = Integer.parseInt(str);//将字符串转换成整数
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
* @param defaultValue 指定的默认值
* @return 整数或默认值
*/
public static int readInt(int defaultValue) {
int n;
for (; ; ) {
String str = readKeyBoard(10, true);
if (str.equals("")) {
return defaultValue;
}
//异常处理...
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的指定长度的字符串
* @param limit 限制的长度
* @return 指定长度的字符串
*/
public static String readString(int limit) {
return readKeyBoard(limit, false);
}
/**
* 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
* @param limit 限制的长度
* @param defaultValue 指定的默认值
* @return 指定长度的字符串
*/
public static String readString(int limit, String defaultValue) {
String str = readKeyBoard(limit, true);
return str.equals("") ? defaultValue : str;
}
/**
* 功能:读取键盘输入的确认选项,Y或N
* 将小的功能,封装到一个方法中.
* @return Y或N
*/
public static char readConfirmSelection() {
char c;
for (; ; ) {//无限循环
//在这里,将接受到字符,转成了大写字母
//y => Y n=>N
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
/**
* 功能: 读取一个字符串
* @param limit 读取的长度
* @param blankReturn 如果为true ,表示 可以读空字符串。
* 如果为false表示 不能读空字符串。
*
* 如果输入为空,或者输入大于limit的长度,就会提示重新输入。
* @return
*/
private static String readKeyBoard(int limit, boolean blankReturn) {
// String str = readKeyBoard(1, false);//包含一个字符的字符串
/*
Scanner scanner = new Scanner(System.in);
System.out.println("请输入多行文本(按Ctrl+D结束):");
while (scanner.hasNextLine()) { // 检查是否有下一行
String line = scanner.nextLine(); // 读取当前行
System.out.println("读取到: " + line);
}
scanner.close();
用户每输入一行后按回车,程序会立即处理该行;输入结束时
(如按 Ctrl+D(Unix/Linux)或 Ctrl+Z(Windows)),循环退出。
*/
//定义了字符串
String line = "";
//scanner.hasNextLine() 判断有没有下一行
while (scanner.hasNextLine()) {
line = scanner.nextLine();//读取这一行
//如果line.length=0, 即用户没有输入任何内容,直接回车
if (line.length() == 0) { // 直接回车的情况
if (blankReturn) return line;//如果blankReturn=true,可以返回空串
// blankReturn参数为真,表示可以接受空字符串所以直接返回空字符串
else continue; //如果blankReturn=false,不接受空串,必须输入内容
// 如果blankReturn为假表示不能接受空字符串重新回到while要求用户输入
}
//如果用户输入的内容大于了 limit,就提示重写输入
//如果用户输入的内容 >0 <= limit ,我就接受
if (line.length() > limit) { // line.length() < 1 || 这个地方老韩添加了这个,应该是写错了
System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
continue;
}
break; // 接受
}
return line;
}
}
package com.alice.houserent.utils;
/*
创建一个TestUtility类来测试Utility类
*/
public class TestUtility {
public static void main(String[] args) {
// 1、Utility.readString(limit);
// 这是一个测试类使用完毕可以直接删除
int limit = 3;
System.out.print("请输入长度最大为"+limit+"的字符串:");
String s = Utility.readString(limit); // 输入一个字符串,长度最大为三
// 这里直接回车还会要求你输出,里面其实调用了另外一个方法
// 开始是没有提示输入的,如果大于了这个limit参数的要求会有提示信息要求
// 输入长度(不能大于xxx)错误,请重新输入的提示。
// 这里没有创建对象就可以调用这个方法,是因为这个方法是一个static的,工具类中的
// 方法一般都会设置成为static的,方便使用者调用
System.out.println("s = " + s);
// 2、另外还重载了一个方法public static String readString(int limit, String defaultValue)
// 可以额外给一个默认的字符串,这次如果为空,就可以返回这个默认的字符串
System.out.print("请输入一个字符串:");
String s1 = Utility.readString(3, "大傻子");
System.out.println("s1 = " + s1);
/*
老韩解读,为什么可以使用类名调用,当一个方法是static的时候就是一个静态方法,
静态方法可以直接使用类名调用。
创建一个A类,然后在A类中创建两个方法,一个方法是普通的成员方法,另外一个方法是static方法
*/
A a = new A();
a.aa();
A.bb();
}
}
class A{
public void aa() {
System.out.println("aa");
}
public static void bb() {
System.out.println("static bb");
}
}
// 03view
package com.alice.houserent.view;
/*
房屋租赁程序框架图(采用最简单的一种模式-分层模式)
框架:1、系统中有哪些类.2、明确类与类之间的调用关系。
创建一个HouseView.java文件
HouseView.java文件的功能:
1、显示界面
2、接收用户的输入
3、调用其他类完成对房屋信息的各种操作(这里的其他类指的是HouseService
将来的界面可能会非常多,所以我们将来不只是创建一个界面,可能会有多个界面
所以要单独创建一个包进行管理houserent.view。
*/
import com.alice.houserent.service.HouseService;
import com.alice.houserent.utils.Utility;
/**
* 1、显示界面
* 2、接受用户的输入
* 3、调用HouseService完成对房屋的信息各种操作
*/
public class HouseView {
String[] MenuItems = {"", "新 增 房 源", "查 找 房 屋", "删 除 房 屋",
"修 改 房 屋", "房 屋 列 表", "退 出"};
int menuItemArrLen = MenuItems.length - 1; // 这个是真实的长度,前面补了一个
HouseService houseService = new HouseService(10);
boolean runMainMenu = true;
String dashedLine = "-----------------";
public void runMain() {
String titleOfMenu = "房屋出租系统";
String titleOfMenuEnd = "系统已经退出";
do {
System.out.println(dashedLine + titleOfMenu + dashedLine);
printTypeOfMainMenu();
System.out.print("请输入你的菜单选项(1-" + menuItemArrLen + "):");
switch (Utility.readMenuSelection(menuItemArrLen)) {
case '1':
addHouse();
break;
case '2':
findHouse();
break;
case '3':
delHouse();
break;
case '4':
updateHouse();
break;
case '5':
houseList();
break;
case '6':
endSys();
break;
}
} while (runMainMenu);
System.out.println(dashedLine + titleOfMenuEnd + dashedLine);
}
public void printTypeOfMainMenu() {
for (int i = 1; i < MenuItems.length; i++) {
System.out.println("\t\t\t\t" + i + " " + MenuItems[i]);
}
}
public void houseList() {
String titleOfHouseList = "展示房屋列表";
String titleOfHouseListEnd = "房屋列表完成";
System.out.println(dashedLine + titleOfHouseList + dashedLine);
System.out.println("编号\t\t房主\t\t电话\t\t地址\t\t月租\t\t状态");
houseService.houseList();
System.out.println(dashedLine + titleOfHouseListEnd + dashedLine);
}
public void addHouse() {
String titleOfAddHouse = "添加新的房屋";
System.out.println(dashedLine + titleOfAddHouse + dashedLine);
System.out.print("姓名:");
String name = Utility.readString(4);
System.out.print("电话:");
String phone = Utility.readString(4);
System.out.print("地址:");
String address = Utility.readString(6);
System.out.print("月租:");
int monthlyRent = Utility.readInt();
System.out.print("状态(未出租/已出租):");
String state = Utility.readString(3, "未出租");
String titleOfAddHouseEnd = houseService.addHouse(name, phone, address, monthlyRent, state);
System.out.println(dashedLine + titleOfAddHouseEnd + dashedLine);
}
public void delHouse() {
String titleOfDelHouse = "正在删除房屋";
String titleOfDelHouseEnd = "退出删除房屋";
String titleOfAbandon = "放弃删除房屋";
System.out.println(dashedLine + titleOfDelHouse + dashedLine);
System.out.print("请选择待删除的房屋编号(-1退出):");
String idOfDelHouse = Utility.readString(8);
if ("-1".equals(idOfDelHouse)) {
System.out.println(dashedLine + titleOfDelHouseEnd + dashedLine);
return ;
}
System.out.print("确认是否删除(Y/N),请小心选择:");
char confirm = Utility.readConfirmSelection();
if (confirm == 'N') {
System.out.println(dashedLine + titleOfAbandon + dashedLine);
return ;
}
String successOrFailure = houseService.delHouse(idOfDelHouse);
System.out.println(dashedLine + successOrFailure + dashedLine);
}
public void endSys() {
System.out.print("确认是否退出(Y/N):");
char terminateTheProgram = Utility.readConfirmSelection();
if (terminateTheProgram == 'Y') {
runMainMenu = false;
}
}
public void findHouse() {
String titleOfFindHouse = "查找房屋信息";
System.out.println(dashedLine + titleOfFindHouse + dashedLine);
System.out.print("请输入要查找的ID:");
int findID = Utility.readInt();
System.out.println(dashedLine + houseService.findHouse(findID) + dashedLine);
}
public void updateHouse() {
String titleOfUpdateHouse = "修改房屋信息";
String titleOfUpdateHouseEnd = "退出修改房屋";
System.out.println(dashedLine + titleOfUpdateHouse + dashedLine);
System.out.print("请选择待修改房屋编号(-1表示退出):");
int updateID = Utility.readInt();
if (updateID == -1) {
System.out.println(dashedLine + titleOfUpdateHouseEnd + dashedLine);
return ;
}
System.out.println(dashedLine + houseService.updateHouse(updateID) + dashedLine);
}
}
// 04Service
package com.alice.houserent.service;
import com.alice.houserent.domain.House;
import com.alice.houserent.utils.Utility;
/*
创建HouseService.java
1、相应HouseView的各个调用
2、完成对房屋信息的各种操作(增删改查)
增删改查也叫做CRUD,create read update delete
同理应该创建一个和业务相关的包管理houserent.service
*/
public class HouseService {
private House[] houses; // 当这个服务调起来之后会初始化这个房屋数组
private int nowHouseNum = 3; // 当前初始化的房子个数
private int lastItemIndex = 3;
public HouseService(int size) { // 可以指定初始化多大的房屋数组
houses = new House[size];
// 初始化给一些数据
// 2 alice 119 昌平区 3000 已出租
houses[0] = new House(1, "张三", "118", "东方名门", 3000, "已出租");
houses[1] = new House(2, "李四", "107", "大花园", 4000, "未出租");
houses[2] = new House(3, "贝贝", "330", "金凤广场", 1500, "已出租");
}
public void houseList() {
for (int i = 0; i < houses.length; i++) {
if (houses[i] == null) {
break;
}
System.out.println(houses[i]);
}
}
/**
* String name = Utility.readString(4);
* System.out.print("电话:");
* String phone = Utility.readString(4);
* System.out.print("地址:");
* String address = Utility.readString(6);
* System.out.print("月租:");
* int monthlyRent = Utility.readInt();
* System.out.print("状态(未出租/已出租):");
* String state = Utility.readString(3, "未出租");
*/
public String addHouse(String name, String phone, String address, int monthlyRent, String state) {
if (nowHouseNum == houses.length) { // 这样就不能添加房屋了
System.out.println("当前房屋已满,不能再添加了!");
return "房屋添加失败";
}
// 更新当前房屋个数并添加到其他房屋后面
House house = new House(++nowHouseNum, name, phone, address, monthlyRent, state);
houses[lastItemIndex++] = house;
return "房屋添加成功";
}
public String delHouse(String idOfDelHouse) {
int houseID = Integer.parseInt(idOfDelHouse);
int index = -1;
for (int i = 0; i < houses.length; i++) {
if(houses[i].getId() == houseID) {
index = i;
break;
}
}
if (index == -1) {
return "删除房屋失败";
}
for (int i = index; i < nowHouseNum - 1; i++) {
houses[i] = houses[i+1];
}
houses[lastItemIndex-- -1] = null;
nowHouseNum--;
return "删除房屋成功";
}
public String findHouse(int findID) {
for (int i = 0; i < houses.length; i++) {
if (houses[i] != null && findID == houses[i].getId()) {
System.out.println(houses[i]);
return "查找房屋成功";
}
}
System.out.println("找不到" + findID + "的房屋...");
return "不存在该房屋";
}
public String updateHouse(int updateID) {
House house = null;
for (int i = 0; i < houses.length; i++) {
if (houses[i] != null && updateID == houses[i].getId()) {
house = houses[i];
}
}
if (house == null) {
System.out.println("房屋不存在...");
return "不存在该房屋";
}
System.out.print("姓名:");
String name = Utility.readString(4, "");
if (!name.equals("")) house.setName(name);
System.out.print("电话:");
String phone = Utility.readString(4, "");
if (!phone.equals("")) house.setPhone(phone);
System.out.print("地址:");
String address = Utility.readString(6, "");
if (!address.equals("")) house.setAddress(address);
System.out.print("月租:");
int monthlyRent = Utility.readInt(house.getRent());
if (monthlyRent != house.getRent()) house.setRent(monthlyRent);
System.out.print("状态(未出租/已出租):");
String state = Utility.readString(3, "");
if (!state.equals("")) house.setState(state);
return "房屋修改成功";
}
}
// 05domain
package com.alice.houserent.domain;
/*
House.java类
一个House类表示一个房屋信息
现在分成界面层,业务层,模型层
这个类放到houserent.domain下面
House一个对象表示一个房屋信息
为此创建一个houserent.domain
*/
/**
* House的对象表示一个房屋信息
*/
public class House {
// 属性从什么地方来呢?
// 可以通过之前给出的界面,编号,房主名字,电话号码,地址,月租和状态,这是六个最基本的
// 如果开发过程中还需要别的属性还可以添加
// 到底如何分析呢?house类有哪些属性可以通过给出的界面分析得到,我们知道,我们至少有六个属性
private int id;
private String name;
private String phone;
private String address;
private int rent;
private String state;
// 构造方法和set以及get方法
public House(int id, String name, String phone, String address, int rent, String state) {
setId(id);
setName(name);
setPhone(phone);
setAddress(address);
setRent(rent);
setState(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方法
// 重写
/**
* 输出的时候格式不好
* 可以自己进行调整
*
* @return String
*/
@Override
public String toString() {
return id + "\t\t" + name + "\t\t" + phone +
"\t\t" + address + "\t" + rent + "\t" + state;
}
}