昨天闲来无事,决定要玩一把大的。于是花费几个小时写了这个「答答租车系统稳定版」。该版本具有如下优势:
- 该系统读取用户输入的一切内容,并给出相应提示,确保用户输入的内容准确。对用户输入字符串或其他数据类型的情况,有相应的报错及提示重新输入的功能。
- 可让用户选择一次性租用多种车辆,并对每一车辆设置单独的租车数目与租车天数。
- 可修改代码的initCarList方法,任意添加新车辆,无需修改其他任何代码。可很方便地添加管理员系统(如增加新车、删除旧车、更改现有车辆参数等等),以后我可能会就此写一个更新版。
- 当然,作者也是初学,水平有限,欢迎大家提出各类修改意见与新增功能建议。
提醒大家,为了保证该程序的稳定性与可扩展性,主程序的代码超过了200行,但我在关键位置给出了详细注释。
闲话少说,下面放出代码。首先定义了基础的Car类:
package com.imooc;
// 新建Car类
public abstract class Car {
private String type;
private int price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return type + "\t" + price;
}
}
随后定义两个接口,分别对应载客与载货。这两个接口其实不是必须,在这里是为了规定载客与载货车辆必须要有getter与setter方法。
package com.imooc;
// 新建接口IPassenger,保证可载客车辆一定有如下方法
public interface IPassenger {
public int getPassCapacity ();
public void setPassCapacity (int passCapacity);
}
package com.imooc;
// 新建接口ICargo,保证可载货车辆一定有如下方法
public interface ICargo {
public int getCargoCapacity ();
public void setCargoCapacity (int cargoCapacity);
}
随后,定义了三个Car的子类:
package com.imooc;
// 新建CarBus类,作为客车,仅能载客
public class CarBus extends Car implements IPassenger {
private int passCapacity;
public CarBus (String type, int price, int passCapacity) {
this.setType(type);
this.setPrice(price);
this.setPassCapacity(passCapacity);
}
public int getPassCapacity() {
return passCapacity;
}
public void setPassCapacity(int passCapacity) {
this.passCapacity = passCapacity;
}
@Override
public String toString() {
return super.toString() + "\t" + passCapacity + "\t---";
}
}
package com.imooc;
// 新建CarTruck类,作为货车,只能载货
public class CarTruck extends Car implements ICargo {
private int cargoCapacity;
public CarTruck (String type, int price, int cargoCapacity) {
this.setType(type);
this.setPrice(price);
this.setCargoCapacity(cargoCapacity);
}
public int getCargoCapacity() {
return cargoCapacity;
}
public void setCargoCapacity(int cargoCapacity) {
this.cargoCapacity = cargoCapacity;
}
@Override
public String toString() {
return super.toString() + "\t---\t" + cargoCapacity;
}
}
package com.imooc;
// 新建CarPickup类,作为皮卡,既能载客,也能载货
public class CarPickup extends Car implements IPassenger, ICargo{
private int passCapacity;
private int cargoCapacity;
public CarPickup (String type, int price, int passCapacity, int cargoCapacity) {
this.setType(type);
this.setPrice(price);
this.setPassCapacity(passCapacity);
this.setCargoCapacity(cargoCapacity);
}
public int getPassCapacity() {
return passCapacity;
}
public void setPassCapacity(int passCapacity) {
this.passCapacity = passCapacity;
}
public int getCargoCapacity() {
return cargoCapacity;
}
public void setCargoCapacity(int cargoCapacity) {
this.cargoCapacity = cargoCapacity;
}
@Override
public String toString() {
return super.toString() + "\t" + passCapacity + "\t" + cargoCapacity;
}
}
主程序:
package com.imooc;
/* 答答租车系统稳定版 v1.0 by Bambrow
* 该系统读取用户输入的一切内容,并给出相应提示,确保用户输入的内容准确。
* 对用户输入字符串或其他数据类型的情况,有相应的报错及提示重新输入的功能。
* 可让用户选择一次性租用多种车辆,并对每一车辆设置单独的租车数目与租车天数。
* 可修改代码的initCarList方法,任意添加新车辆,无需修改其他任何代码。
* 作者会继续进行维护和改进,可能以后会增加管理员系统。
* 可任意参考,转载请注明作者或保留该注释。
*/
// 导入包
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.stream.IntStream;
public class Demo {
public static void main(String[] args) {
System.out.println("欢迎来到答答租车系统!");
List carList = initCarList(); // 为了保证随时添加与删除项目,使用List功能
for( ; ; ) { // 设置无条件循环
System.out.println("若您是租车客户,请输入1;"
+ "退出请输入0。");
int choice;
try{
choice = Integer.parseInt(getInput());
}catch(Exception e){
System.out.println("指令有误!请输入正确的指令。");
continue;
} // 确保输入的为数字,而不是别的字符
if(choice == 0) break; // 若输入0,结束循环
else if(choice == 1) {
rentCars(carList); // 若输入1,开始租车
System.out.println();
}
else{
System.out.println("指令有误!请输入正确的指令。");
continue;
} // 若输入其他数字,重新开始循环
}
System.out.println("感谢您使用答答租车系统!");
}
// 生成初始化的可租车列表
private static List initCarList() {
List<Car> carList = new ArrayList<Car>(); // 初始化List,确保每一项都是Car类
carList.add(new CarBus("小型客车", 500, 6));
carList.add(new CarBus("大型客车", 1000, 15));
carList.add(new CarTruck("小型货车", 400, 2));
carList.add(new CarTruck("大型货车", 800, 10));
carList.add(new CarPickup("小型皮卡", 500, 2, 1));
carList.add(new CarPickup("大型皮卡", 900, 4, 2));
return carList; // 添加完每一辆车后返回List
} // 可以随时使用carList.add添加新车辆,而无需修改其他任何代码
// 输出租车列表,用到了每一类中重写的toString方法
private static void printCarList(List carList) {
System.out.println("以下是可用车型:");
System.out.println("序号\t车型\t租金\t载客量\t载货量");
for(int i = 0; i < carList.size(); i++) {
System.out.println((i + 1) + "\t" + (carList.get(i)).toString());
}
}
// 客户选车功能,该功能无需用户提前输入租车的类型数目,因此全部使用无需预先确定长度的List功能
private static List selectCars(List carList) {
List<Integer> rentArray = new ArrayList<Integer>(); // 储存客户选过的序号
List<Car> selectCars = new ArrayList<Car>(); // 储存用户选过的车
System.out.println("请输入租车序号,以回车分隔。输入0结束输入:");
for( ; ; ) {
System.out.println("请输入车辆序号(1-" + carList.size() + "):");
boolean repeated = false;
int carNum;
try{
carNum = Integer.parseInt(getInput());
}catch(Exception e){
System.out.println("输入不正确!请输入正确的序号。");
continue;
} // 确保输入的为数字,而不是其他字符
if(carNum == 0) break; // 输入0,退出循环
else if(carNum > 0 && carNum <= carList.size()) { // 确保输入的数字在范围内
for(int i = 0; i < rentArray.size(); i++){
if(carNum == rentArray.get(i)) {
System.out.println("您已输入过该车型!请重新输入序号。");
repeated = true;
break; // 若输入的序号已经选择过,则输出选择重复信息并重新选择
}
}
if(!repeated) {
rentArray.add(carNum);
selectCars.add((Car) carList.get(carNum - 1));
} // 若输入的序号不重复,则加入选择的车辆列表
}
else{
System.out.println("输入不正确!请输入正确的序号。");
continue;
} // 确保输入的数字在范围内
}
return selectCars; // 返回选好的车辆List
}
// 读取租车数目功能
private static int rentCount() {
for( ; ; ) {
System.out.println("请输入租车数(1-50):");
int rentCount;
try{
rentCount = Integer.parseInt(getInput());
}catch(Exception e){
System.out.println("输入不正确!请输入正确的租车数。");
continue;
} // 确保输入的为数字,而不是其他字符
if(rentCount >= 1 && rentCount <= 50) return rentCount; // 输入正确
else System.out.println("输入不正确!请输入正确的租车数。"); // 输入不正确
}
}
// 对每一种选好的车辆,读取相应的租车数目
private static int[] rentNumArray(List carList) {
int[] rentNumArray = new int[carList.size()]; // 使用数组存储每一种车辆的数目
for(int i = 0; i < carList.size(); i++) {
System.out.println("请输入选定列表里,第" + (i+1) + "辆车的租车数量:");
rentNumArray[i] = rentCount(); // 调用读取租车数目方法
}
return rentNumArray; // 返回租车数目数组
}
// 读取租车天数功能
private static int rentDays() {
for( ; ; ) {
System.out.println("请输入租车天数(1-365):");
int rentDays;
try{
rentDays = Integer.parseInt(getInput());
}catch(Exception e){
System.out.println("输入不正确!请输入正确的租车天数。");
continue;
} // 确保输入的为数字,而不是其他字符
if(rentDays >= 1 && rentDays <= 365) return rentDays; // 输入正确
else System.out.println("输入不正确!请输入正确的租车天数。"); // 输入不正确
}
}
// 对每一种选好的车辆,读取相应的租车天数
private static int[] rentDayArray(List carList) {
int[] rentDayArray = new int[carList.size()]; // 使用数组存储每一种车辆的天数
for(int i = 0; i < carList.size(); i++) {
System.out.println("请输入选定列表里,第" + (i+1) + "辆车的租车天数:");
rentDayArray[i] = rentDays(); // 调用读取租车天数方法
}
return rentDayArray; // 返回租车天数数组
}
// 打印订单
private static void printOrder(List carList,
int[] rentNumArray, int[] rentDayArray) {
int[] rentSinglePriceTotal = new int[carList.size()];
int[] rentSinglePassTotal = new int[carList.size()];
int[] rentSingleCargoTotal = new int[carList.size()];
// 三个数组分别存储总价、总载客量与总载货量
System.out.println("以下是您的订单:");
System.out.println("序号\t车型\t租金\t载客量\t载货量"
+ "\t租用数量\t租用天数\t消费数额");
for(int i = 0; i < carList.size(); i++) {
rentSinglePriceTotal[i] = ((Car) carList.get(i)).getPrice()
* rentNumArray[i] * rentDayArray[i]; // 计算每一种车的总价
System.out.println((i + 1) + "\t" + (carList.get(i)).toString()
+ "\t" + rentNumArray[i] + "\t" + rentDayArray[i]
+ "\t" + rentSinglePriceTotal[i]);
try{
rentSinglePassTotal[i] =
((CarBus) carList.get(i)).getPassCapacity()
* rentNumArray[i];
}catch(Exception eCarBus){
try{
rentSinglePassTotal[i] =
((CarPickup) carList.get(i)).getPassCapacity()
* rentNumArray[i];
}catch(Exception eCarPickup){
rentSinglePassTotal[i] = 0;
}
} // 双重try嵌套,如果车辆有载客功能,则存储一天的总载客量,否则存储0
try{
rentSingleCargoTotal[i] =
((CarTruck) carList.get(i)).getCargoCapacity()
* rentNumArray[i];
}catch(Exception eCarTruck){
try{
rentSingleCargoTotal[i] =
((CarPickup) carList.get(i)).getCargoCapacity()
* rentNumArray[i];
}catch(Exception eCarPickup){
rentSingleCargoTotal[i] = 0;
}
} // 双重try嵌套,如果车辆有载货功能,则存储一天的总载货量,否则存储0
}
int rentTotal = IntStream.of(rentSinglePriceTotal).sum();
int passCapacityTotal = IntStream.of(rentSinglePassTotal).sum();
int cargoCapacityTotal = IntStream.of(rentSingleCargoTotal).sum();
// 将三个数组的值分别相加求和
System.out.println("总载客量(人/天):" + passCapacityTotal);
System.out.println("总载货量(人/天):" + cargoCapacityTotal);
System.out.println("订单总价(元):" + rentTotal); // 所有车的订单总价
}
// 读取用户输入方法
private static String getInput() {
Scanner input = new Scanner(System.in); // 新建Scanner
try{
return input.next();
}catch (Exception e){
return null; // 确保用户输入了内容
}finally{
input.nextLine(); // 防止下次调用时出现读取错误
}
}
// 开始租车
private static void rentCars(List carList) {
printCarList(carList); // 打印现有的车辆列表
List selectCars = selectCars(carList); // 用户开始选车
System.out.println("这是您选定的租车列表:");
printCarList(selectCars); // 打印选定的车辆列表
int[] rentNumArray = rentNumArray(selectCars); // 用户对每一种车输入租车数量
int[] rentDayArray = rentDayArray(selectCars); // 用户对每一种车输入租车天数
printOrder(selectCars, rentNumArray, rentDayArray); // 打印最终订单
}
}
各位有什么不明白的,可以留言。有什么改进建议,也可以留言。Thanks!
热门评论
为么你们学的那么快呢,我怎么就只有思路,不知到怎么用代码表达。真是愁人啊。
为么你们学的那么快呢,我怎么就只有思路,不知到怎么用代码表达。真是愁人啊。
为什么要用抽象类car ;直接继承不好么