一、实验目标
本实验的目标是将面向对象基础和高级开发融合起来,让学生能运用所学知识解决复杂工程问题。支撑计算机类专业基础实践能力、专业核心能力、综合创新能力的培养。
二、所需技能
本实验要求掌握基于面向对象的综合软件开发流程和相关技术。完成面向对象综合实验的实验内容,掌握计算机及相关方法对复杂的工程问题进行分析的方法,具备使用现代技术及相关工具的能力;掌握设计相应的实验方案的方法,具备应用复杂计算系统开发的能力, 并在设计和开发过程中体现出创新意识。
三、实验要求
1、请设计并实现一个汽车租赁系统V4.0(题目可以自拟),需求如下。
1)系统分为管理员和用户角色登录,不同的角色有不同的权限操作;
2)管理员功能:查看、添加、修改和删除车辆信息,查看营业额;
3)用户功能(VIP用户):登录后,可以查看车辆、租车、换车,模拟付款等;
4)车辆:基础版(只考虑小汽车Car),高级版(考虑三种车型Car,Bus, Trunk);
5)存储:用文件或数据库进行数据存储。
2、提交材料清单和评分细则
(1)系统说明书(50分)
1)、汽车租赁系统的需求分析;(5分)
2)、根据需求分析,画出系统功能结构图;(5分)
3)、结合需求分析和功能模块,画出系统的类图;(20分,按照设计有对应类代码,缺少一个扣5分,直到该项扣完为止)
4)、系统测试,合理设置测试用例,验证系统是否正常运行。(20分)
(2)代码实现(20分)
(3)面向对象设计方法和Java特性考察点(15分,每一个3分,加满为止)
继承、多态、集合框架、异常处理、多线程、工厂模式
(4)汇报展示(15分)
针对实验的内容制作汇报PPT(10分钟
四、源代码
Vehicle.java
public abstract class Vehicle {
private String brand;//品牌
private String type;//型号
private String id;//车牌号
private String rent;//租金
private String status;//状态(待租用/已租用)
public Vehicle(){}
public Vehicle(String brand, String type, String id, String rent, String status) {
this.brand = brand;
this.type = type;
this.id = id;
this.rent = rent;
this.status = status;
}
public String getBrand() {
return brand;
}
public String getType() {
return type;
}
public String getId() {
return id;
}
public String getRent() {
return rent;
}
public String getStatus() {
return status;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void setType(String type) {
this.type = type;
}
public void setId(String id) {
this.id = id;
}
public void setRent(String rent) {
this.rent = rent;
}
public void setStatus(String status) {
this.status = status;
}
public abstract String toString();
}
Car.java
//小轿车
public class Car extends Vehicle {
public Car(){}
public Car(String brand, String type, String id, String rent, String status) {
super(brand, type, id, rent, status);
}
@Override
public String toString() {
return getBrand() + " " + getType() + " " + getId() + " " + getRent() + " " + getStatus();
}
}
Bus.java
//客车
public class Bus extends Vehicle {
private String capacity; // 载客量
public Bus() {
}
public Bus(String brand, String type, String id, String rent, String status, String capacity) {
super(brand, type, id, rent, status);
this.capacity = capacity;
}
public String getCapacity() {
return capacity;
}
public void setCapacity(String capacity) {
this.capacity = capacity;
}
public String toString() {
return getBrand() + " " + getType() + " " + getId() + " " + getRent() + " " + getCapacity() + " " + getStatus();
}
}
Trunk.java
//货车
public class Trunk extends Vehicle{
private String loadCapacity; // 载重量
public Trunk(){}
public Trunk(String brand, String type, String id, String rent, String status, String loadCapacity) {
super(brand, type, id, rent, status);
this.loadCapacity = loadCapacity;
}
public String getLoadCapacity() {
return loadCapacity;
}
public void setLoadCapacity(String loadCapacity) {
this.loadCapacity = loadCapacity;
}
@Override
public String toString() {
return getBrand()+" "+getType()+" "+getId()+" "+getRent()+" "+getLoadCapacity()+" "+getStatus();
}
}
User.java
import java.util.*;
//普通用户
public class User {
String id;//ID账号
String password;//登录密码
public User() {}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int register() {
Scanner sc = new Scanner(System.in);
int p=0;
int cnt = 0;
int maxAttempts = 3; // 最大尝试次数
System.out.println("----汽车租赁系统----");
System.out.println("请输入ID账号:");
while (true) {
if (cnt == 1) {
break;
}
String ID = sc.next();
String password = "";
String successMessage = "";
Map<String, String> userCredentials = new HashMap<>();
userCredentials.put("123", "abc");
userCredentials.put("1234", "abcd");
userCredentials.put("12345", "abcde");
if (userCredentials.containsKey(ID)) {
password = userCredentials.get(ID);
switch (ID) {
case "123":
successMessage = "登录成功!尊敬的用户!";
p = 1;
break;
case "1234":
successMessage = "登录成功!尊敬的VIP用户!";
p = 2;
break;
case "12345":
successMessage = "登录成功!尊敬的管理员!";
p = 3;
break;
}
} else {
System.out.println("账号不存在! 请重新输入ID账号:");
continue;
}
System.out.println("请输入密码:");
for (int attempt = 0; attempt < maxAttempts; attempt++) {
String pwd = sc.next();
if (pwd.equals(password)) {
System.out.println(successMessage);
cnt++;
return p;
}
System.out.println("密码错误! 请重新输入密码:");
}
System.out.println("超过最大尝试次数,登录失败!");
return -1;
}
return cnt;
}
public void findVehicle(TreeSet<Vehicle> v) {
if (v.isEmpty()) {
System.out.println("无信息!请先添加信息再查询!");
return;
}
for (Vehicle vehicle : v) {
System.out.println(vehicle.toString());
}
}
public void rentVehicle(TreeSet<Vehicle> v,int d) {
Scanner sc = new Scanner(System.in);
Vehicle currentcar = null;
System.out.println("请输入要租赁的车辆的车牌号:");
currentcar = inputVehicleId(v);
System.out.println("请输入租赁天数:");
int day = sc.nextInt();
int totalRent = day * Integer.parseInt(currentcar.getRent().substring(0, currentcar.getRent().length() - 3));
System.out.print("您的订单为:");
System.out.println(currentcar.toString() + ",租期" + day + "天,"
+ "日租金:" + currentcar.getRent() + "元," + "总租金:" + totalRent+"元");
if(d==1){
Admin.turnover+=totalRent;
System.out.println("没有优惠,您需要付款:"+totalRent+"元");
}
if(d==2) {
if(day<7){
Admin.turnover+=totalRent;
System.out.println("租期小于7天,没有优惠");
}
else{
Admin.turnover+=totalRent;
totalRent=(int)VIPUser.dicount(day,totalRent);
System.out.println("您是VIP用户!有优惠,您需要付款:"+totalRent+"元");
}
}
currentcar.setStatus("已租");
}
public void replaceVehicle(TreeSet<Vehicle> v,int d) {
Scanner sc = new Scanner(System.in);
Vehicle currentcar = null;
System.out.println("请输入要替换的车辆的车牌号:");
currentcar = inputVehicleId(v);
currentcar.setStatus("空闲");
System.out.println("请输入要替换的新车辆的车牌号:");
currentcar = inputVehicleId(v);
System.out.println("更换成功!");
System.out.println("请输入租赁天数:");
int day = sc.nextInt();
int totalRent = day * Integer.parseInt(currentcar.getRent().substring(0, currentcar.getRent().length() - 3));
System.out.print("您的订单为:");
System.out.println(currentcar.toString() + ",租期" + day + "天,"
+ "日租金:" + currentcar.getRent() + "元," + "总租金:" + totalRent+"元");
if(d==1){
Admin.turnover+=totalRent;
System.out.println("没有优惠,您需要付款:"+totalRent+"元");
}
if(d==2) {
if(day<7){
Admin.turnover+=totalRent;
System.out.println("租期小于7天,没有优惠");
}
else{
Admin.turnover+=totalRent;
totalRent=(int)VIPUser.dicount(day,totalRent);
System.out.println("您是VIP用户!有优惠,您需要付款:"+totalRent+"元");
}
}
currentcar.setStatus("已租");
}
public void returnCar (TreeSet<Vehicle> v) {
Scanner sc = new Scanner(System.in);
Vehicle currentcar = null;
System.out.println("请输入要还车的车牌号:");
currentcar = inputVehicleId(v);
currentcar.setStatus("空闲");
System.out.println("还车成功!");
}
public void payment() {
System.out.println("是否付款(1 是/2 否):");
Scanner sc = new Scanner(System.in);
String s = sc.next();
if (s.equals("1")) {
System.out.println("付款成功!");
} else {
System.out.println("订单已被取消!");
}
}
public Vehicle inputVehicleId(TreeSet<Vehicle> v) {
Scanner sc = new Scanner(System.in);
while (true) {
id = sc.nextLine();
boolean found = false;
Iterator<Vehicle> iterator = v.iterator();
while (iterator.hasNext()) {
Vehicle vehicle = iterator.next();
if (vehicle.getId().equals(id)) {
return vehicle;
}
}
if (!found) {
System.out.println("该车辆不存在!\n请重新输入你要修改的车辆的车牌号:");
} else {
break; // 如果找到了并删除,则退出循环
}
}
return null;
}
}
VIPUser.java
//VIP用户
public class VIPUser extends User{
public VIPUser() {}
public static double dicount(int day,int totalRent) {
if(day>=7&&day<=14)
return totalRent*=0.9;
else if(day>=15&&day<=30)
return totalRent*=0.85;
else if(day>30&&day<=60)
return totalRent*=0.8;
else
return totalRent*=0.7;
}
}
Admin
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;
//管理员
public class Admin extends User {
public static int turnover;//营业额
public Admin() {}
public void addVehicle(TreeSet<Vehicle> v) {
try (Scanner sc = new Scanner(System.in)) {
System.out.println("请输入车辆类型(汽车/客车/货车):");
String model = sc.nextLine();
while (!model.equals("汽车") && !model.equals("客车") && !model.equals("货车")) {
System.out.println("输入的车辆类型无效,请重新输入(汽车/客车/货车):");
model = sc.nextLine();
}
String id = "";
while (true) {
System.out.println("请输入车辆车牌号:");
id = sc.nextLine();
if (isIdUnique(v, model, id)) {
break;
} else {
System.out.println("该车牌号已存在,请重新输入车牌号:");
}
}
System.out.println("请输入车辆品牌:");
String brand = sc.nextLine();
System.out.println("请输入车辆型号:");
String type = sc.nextLine();
System.out.println("请输入车辆日租金:");
String rent = sc.nextLine();
System.out.println("请输入车辆空闲状态:");
String status = sc.nextLine();
// 创建车辆对象
Vehicle v1 = null;
if (model.equals("客车")) {
System.out.println("请输入车辆载客量:");
String capacity = sc.nextLine();
v1 = new Bus(brand, type, id, rent + "元\\天", status, capacity);
} else if (model.equals("货车")) {
System.out.println("请输入车辆载重:");
String loadCapacity = sc.nextLine();
v1 = new Trunk(brand, type, id, rent + "元\\天", status, loadCapacity);
} else {
v1 = new Car(brand, type, id, rent + "元\\天", status);
}
// 添加车辆对象到集合中
v.add(v1);
System.out.println("添加成功!");
} catch (Exception e) {
System.err.println("发生错误: " + e.getMessage());
}
}
/**
* 检查给定ID在特定车辆模型中是否唯一
*
* @param v 车辆的集合,用于查找是否存在相同ID的车辆
* @param model 车辆模型类型,决定使用哪种类型的车辆对象进行比较
* @param id 需要检查的车辆ID,用于确定是否唯一
* @return 如果指定ID在给定模型中是唯一的,则返回true;否则返回false
*/
private boolean isIdUnique(TreeSet<Vehicle> v, String model, String id) {
// 根据不同的车辆模型类型,创建相应的车辆对象,并检查集合中是否包含相同ID的对象
switch (model) {
case "汽车":
// 检查汽车模型中ID是否唯一
return !v.contains(new Car("", "", id, "", ""));
case "客车":
// 检查客车模型中ID是否唯一
return !v.contains(new Bus("", "", id, "", "", ""));
case "货车":
// 检查货车模型中ID是否唯一
return !v.contains(new Trunk("", "", id, "", "", ""));
default:
// 默认情况下返回false,表示不处理已知模型之外的情况
return false;
}
}
public void deleteVehicle(TreeSet<Vehicle> v) {
if (v.isEmpty()) {
System.out.println("无信息!请先添加信息再删除!");
return;
}
Scanner sc = new Scanner(System.in);
String id;
System.out.println("请输入你要删除的车辆的车牌号:");
while (true) {
id = sc.nextLine();
boolean found = false;
Iterator<Vehicle> iterator = v.iterator();
while (iterator.hasNext()) {
Vehicle vehicle = iterator.next();
if (vehicle.getId().equals(id)) {
iterator.remove(); // 使用迭代器删除元素
System.out.println("删除成功!");
found = true;
break;
}
}
if (!found) {
System.out.println("该车辆不存在!\n请重新输入你要删除的车辆的车牌号:");
} else {
break; // 如果找到了并删除,则退出循环
}
}
}
public void updateVehicle(TreeSet<Vehicle> v) {
if (v.isEmpty()) {
System.out.println("无信息!请先添加信息!");
return;
}
Scanner sc = new Scanner(System.in);
String id;
Vehicle currentcar = null;
System.out.println("请输入你要修改的车辆的车牌号:");
currentcar = inputVehicleId(v);;//验证车牌号是否存在
System.out.println("请输入新的车辆类型(汽车/客车/货车):");
String model = sc.nextLine();
while (!model.equals("汽车") && !model.equals("客车") && !model.equals("货车")) {
System.out.println("输入的车辆类型无效,请重新输入(汽车/客车/货车):");
model = sc.nextLine();
}
System.out.println("请输入新车辆品牌:");
String brand = sc.nextLine();
currentcar.setBrand(brand);
System.out.println("请输入新车辆型号:");
String type = sc.nextLine();
currentcar.setType(type);
System.out.println("请输入新车辆日租金:");
String rent = sc.nextLine();
currentcar.setRent(rent + "元\\天");
System.out.println("请输入新车辆空闲状态:");
String status = sc.nextLine();
currentcar.setStatus(status);
if (model.equals("客车")) {
System.out.println("请输入新车辆载客量:");
String capacity = sc.nextLine();
((Bus) currentcar).setCapacity(capacity);
}
if (model.equals("货车")) {
System.out.println("请输入新车辆载重:");
String loadCapacity = sc.nextLine();
((Trunk) currentcar).setLoadCapacity(loadCapacity);
}
sc.close();
System.out.println("修改成功!");
}
public void viewTurnover(TreeSet<Vehicle> v) {
System.out.println("营业额为:"+turnover+"元");
}
}
MainDemo.java
import java.io.*;
import java.util.*;
public class MainDemo {
/**
* 主程序入口
* 创建一个TreeSet集合,用于存储Vehicle对象,并根据特定规则进行排序
* 读取用户输入,根据用户类型调用不同的菜单功能
* 最后,将所有车辆信息写入文件
*/
public static void main(String[] args) throws IOException {
// 创建TreeSet集合,使用自定义Comparator进行排序
TreeSet<Vehicle> v = new TreeSet<>(new Comparator<Vehicle>() {
@Override
public int compare(Vehicle o1, Vehicle o2) {
// 首先比较车辆类名
int num1 = o1.getClass().getName().compareTo(o2.getClass().getName());
// 如果类名相同,则比较品牌
int num2 = num1 == 0 ? o1.getBrand().compareTo(o2.getBrand()) : num1;
// 如果品牌也相同,则比较状态
int num3 = num2 == 0 ? o1.getStatus().compareTo(o2.getStatus()) : num2;
// 如果状态还相同,则比较类型
int num4 = num3 == 0 ? o1.getType().compareTo(o2.getType()) : num3;
return num4;
}
});
// 添加汽车信息
v.add(new Car("奔驰", "C200", "沪A12345", "50元\\天", "空闲"));
v.add(new Car("宝马", "3系", "川A12345", "60元\\天", "已租"));
v.add(new Car("大众", "CC", "川B12345", "35元\\天", "空闲"));
v.add(new Car("奥迪", "A4L", "鲁A12345", "55元\\天", "空闲"));
// 添加大巴车信息
v.add(new Bus("金龙", "XMQ6127", "鲁B12345", "200元\\天", "空闲", "限载50人"));
v.add(new Bus("宇通", "ZK6127", "京A12345", "210元\\天", "已租", "限载60人"));
// 添加货车信息
v.add(new Trunk("解放", "J6P", "云T12345", "150元\\天", "空闲", "载货量100吨"));
v.add(new Trunk("东风", "天龙", "渝T12345", "160元\\天", "已租", "载货量45吨"));
// 把所有车辆信息写入文件
try (BufferedWriter bw = new BufferedWriter(new FileWriter("car.txt"))) {
for (Vehicle v1 : v) {
bw.write(v1.toString());
bw.newLine();
}
}
// 创建User对象,模拟用户操作
User u = new User();//货车川T2345好运JS空闲
int d = u.register();
// 根据用户类型调用不同的菜单功能
if (d == 3) {
adminMenu(v);
} else {
userMenu(v, d);
}
// 把最终所有车辆信息写入文件
try (BufferedWriter bw = new BufferedWriter(new FileWriter("car.txt"))) {
for (Vehicle v1 : v) {
bw.write(v1.toString());
bw.newLine();
}
}
}
private static void adminMenu(TreeSet<Vehicle> v) {
Scanner sc = new Scanner(System.in);
while (true) {
Admin a = new Admin();
System.out.println("1 添加车辆信息 2 删除车辆信息 3 修改车辆信息 4 查看车辆信息 5查看营业额 6 退出系统");
System.out.println("请输入你的选择:");
try {
String line = sc.next();
switch (line) {
case "1":
a.addVehicle(v);
break;
case "2":
a.deleteVehicle(v);
break;
case "3":
a.updateVehicle(v);
break;
case "4":
a.findVehicle(v);
break;
case "5":
a.viewTurnover(v);
break;
case "6":
System.out.println("退出系统");
return; // 退出循环并结束程序
default:
System.out.println("无效的选择,请重新输入!");
}
} catch (NoSuchElementException e) {
System.out.println("输入流已结束,程序将退出。");
break; // 退出循环
}
}
}
private static void userMenu(TreeSet<Vehicle> v, int d) {
Scanner sc = new Scanner(System.in);
while (true) {
User user = d == 2 ? new VIPUser() : new User();
System.out.println("1 查看车辆信息 2 租用车辆 3 更换车辆 4 付款 5 还车 6 退出系统");
System.out.println("请输入你的选择:");
String line = sc.nextLine();
switch (line) {
case "1":
user.findVehicle(v);
break;
case "2":
user.rentVehicle(v, d);
break;
case "3":
user.replaceVehicle(v, d);
break;
case "4":
user.payment();
break;
case "5":
user.returnCar(v);
break;
case "6":
System.out.println("退出系统");
return; // 优雅地退出程序
default:
System.out.println("操作错误,请重新输入!");
}
}
}
}
五、系统说明书
汽车租赁系统V4.0系统说明书
(一)需求分析
1、用户
(1)管理员:负责系统的后台管理,对车辆信息和营业额进行操作。
(2)VIP 用户:有租车需求的用户,通过系统进行租车相关操作。
2、场景
(1)管理员场景
1)当有新车辆购入或车辆信息需要更新时,管理员需要添加或修改车辆信息。
2)当车辆信息更新,如维修后某些属性改变,车辆报废或不再用于租赁时,管理员需要删除车辆信息。
3)定期查看营业额以了解经营状况。
(2)VIP 用户场景
1)用户有出行需求,需要租车时,登录系统查看车辆信息并选择合适的车辆进行租赁。
2)在租车期间,如果车辆出现问题或有其他需求,可能会进行换车操作。
3)还车结束后需要模拟付款完成交易。
3、问题
(1)管理员问题
1)如何高效地管理车辆信息,确保信息的准确性和及时性。
2)查看营业额时,如果没有一个有效的系统进行统计,计算过程可能会很繁琐且容易出错。
(2)VIP 用户问题
1)查看车辆时,如果系统界面不友好或车辆信息不完整,可能无法快速准确地找到合适的车辆。
2)租车和换车过程中,如果流程不清晰或系统操作复杂,会给用户带来不便。
3)付款时,如果没有模拟付款功能或付款方式不安全,会影响用户体验和交易安全。
4、方案
(1)管理员方案
1)提供车辆信息管理模块,包括添加、修改和删除车辆信息的功能。
2)通过数据存储(文件或数据库)记录车辆租赁交易信息,以便准确计算营业额并提供查看功能。
(2). VIP 用户方案
1)提供车辆查询功能,用户可以根据车型、价格等条件筛选车辆。
2)设计简洁的租车和换车流程,在系统中明确操作步骤。
3)采用安全的模拟付款方式,如加密技术确保交易安全。
(二)功能结构图
-
(三)类设计、类图
总共8个类(Vehicle父类;cars三种车辆类型; user用户、VIP用户和管理员;MainDemo 主类)
Admin:管理员类,有车辆管理及营业额查看功能。
Bus:大巴车类,含载客量属性。
Car:小轿车类。
MainDemo:程序入口,处理登录及菜单导航。
Trunk:货车类,有载重量属性。
User:普通用户类,涵盖注册及车辆操作功能。
VIPUser:VIP 用户类,有租车折扣计算方法。
Vehicle:车辆抽象父类,定义通用属性和方法。
该系统所用java技术栈:继承、多态、异常、泛型、文件、集合。
-
(四)系统测试设计
用例编号 | 用例标题 | 输入数据 | 预期结果 |
1 | VIP用户登录 | 账号: 1234 密码:abcd | VIP用户登录成功 |
2 | 普通用户登录 | 账号: 123 密码:abc | 普通用户登录成功 |
3 | 租车 | 车牌号:云T12345 天数 45(天) | 租车成功,并模拟付款 |
4 | 还车 | 还车操作 | 还车成功 |
5 | 付款 | 付款操作 | 付款成功 |
6 | 查看车辆信息 | 查看操作 | 查看成功 |
7 | 管理员登录 | 账号: 12345 密码:abcde | 管理员登录成功 |
8 | 修改车辆信息 | 金龙(修改后的品牌) 200(修改后的日租金) XMQ27(修改后车类型) 50座(修改座位数) | 修改成功 |
9 | 添加多个类型的车辆信息 | 1(轿车) 大众(品牌)CC系(类型) 川A12345(车牌号) 120(日租金) | 添加成功 |
10 | 删除车辆 | 4(删除选项) 京A12345(车牌号) | 删除成功 |
11 | 查看营业额 | 5(查看营业额的选项) | 查看成功 |
六、部分运行结果
VIP用户登录
查看车辆信息
租车并结算付款
还车
添加车辆信息
标签:String,System,V4.0,汽车,车辆,println,public,租赁,out From: https://blog.csdn.net/GZH_mxjx/article/details/143362035