边界自校验、失败域统一、映射显式化

/**
复制代码
* 把第 1周「报价计算器-第一步」重构:每个功能一个方法,main方法里只剩菜单流程,代码行数控制在30行内 * <p> * Day22: * 报价计算器加档次逻辑:经济800/舒适1200/豪华1800元每 ㎡ * 把报价计算拆成方法:calcMaterial(area)算材料费=面积×600,calcLabor(area)算人工费=面积×300,main中调用 * 1、正则表达式 * 2、面积输入,装修档次选择 * 3、switch -case * 4、getHouseArea() // 获取房屋面积 * 5、getUnitPrice() // 获取装修档次对应的单价 * 6、getPackageDesc() // 获取装修档次的菜单编号对应的菜单描述 * 7、getMenuNumber() // 获取菜单编号,传递给getPackageDesc() 和 getUnitPrice() * 8、quoteCalc() // 计算装修总价 * */ import java.util.Scanner; public class Day26QuoteCalc { private static final int LEVEL_ECONOMY_MENU_NUMBER = 1; // 装修档次(经济套餐)的菜单编号 private static final int LEVEL_COMFORT_MENU_NUMBER = 2; // 装修档次(舒适套餐)的菜单编号 private static final int LEVEL_LUXURY_MENU_NUMBER = 3; // 装修档次(豪华套餐)的菜单编号 private static final double LEVEL_ECONOMY_UNIT_PRICE = 800; // 装修档次(经济套餐)的单价 private static final double LEVEL_COMFORT_UNIT_PRICE = 1200; // 装修档次(舒适套餐)的单价 private static final double LEVEL_LUXURY_UNIT_PRICE = 1800; // 装修档次(豪华套餐)的单价 private static final String LEVEL_ECONOMY_DESC = "经济套餐"; // 装修档次(经济套餐)的描述 private static final String LEVEL_COMFORT_DESC = "舒适套餐"; // 装修档次(舒适套餐)的描述 private static final String LEVEL_LUXURY_DESC = "豪华套餐"; // 装修档次(豪华套餐)的描述 private static final int INPUT_ZERO = 0; // 返回值为0,就是输入为0 private static final int INPUT_EXIT = -1; // 返回值为-1,就是要退出程序 private static final int INPUT_IS_BLANK = -2; // 返回值为-2,就是没有输入 private static final int INPUT_INVALID = -3; // 返回值为-3,就是输入无效 private static final int INPUT_INVALID_MENU_NUMBER = -3; // 返回值为-3,就是菜单编号输入无效 private static final String AREA_EXIT_TIP = "感谢使用,See you next time."; // 程序退出的提示 private static final String AREA_IS_BLANK_TIP = "没有输入,请重新输入面积(m²)!"; // 没有输入面积的提示 private static final String AREA_INVALID_TIP = "输入了无效的面积,请重新输入面积(m²)!"; // 面积输入无效的提示 private static final String AREA_ZERO_TIP = "面积要大于0,请重新输入面积(m²)!"; // 面积为0的提示 private static final String MENU_NUMBER_INVALID_TIP = "菜单编号输入无效,请输入装修套餐(1-经济|2-舒适|3-豪华)!"; // 装修档次菜单编号输入无效的提示 public static void main(String[] args) { Scanner in = new Scanner(System.in); String printTitle = "\n------------------------------装修金额(套餐)计算器------------------------------\n"; String printLine = "-----------------------------------------------------------------------------\n"; String printAreaTip = "房屋面积是:%,.2f m²"; String printLevelPackageTip = "装修套餐是:%s"; String printLevelUnitPriceTip = "套餐单价是:%,.2f 元/m²"; String printAmountTip = "装修金额是:%,.2f 元"; while (true) { String inputAreaTitle = "请输入房屋面积(m²),回车确定|exit退出:"; String inputPackage = "请选择装修套餐(1-经济|2-舒适|3-豪华):"; System.out.print(inputAreaTitle); String line = in.nextLine().strip(); // 判断面积,合法的话(返回值为>0)就进行菜单展示和选择 double houseArea = getHouseArea(line); if (houseArea == INPUT_INVALID) { // 判断返回值,-3就提示“输入了无效的面积,请重新输入面积(m²)!” System.out.println(AREA_INVALID_TIP); continue; } if (houseArea == INPUT_IS_BLANK) { // 判断返回值,-2就提示“没有输入,请重新输入面积(m²)!” System.out.println(AREA_IS_BLANK_TIP); continue; } if (houseArea == INPUT_EXIT) { // 判断返回值,-1就退出 System.out.println(AREA_EXIT_TIP); break; } if (houseArea == INPUT_ZERO) { // 判断面积,输出面积为0(返回值为0)的提示“面积要大于0,请重新输入面积(m²)!” System.out.println(AREA_ZERO_TIP); continue; } // 菜单流程 int menuNum; while(true) { System.out.print(inputPackage); String num = in.nextLine().strip(); menuNum = getMenuNumber(num); // 获取装修档次菜单编号 if (menuNum >= 1 && menuNum <= 3) { break; } System.out.println(MENU_NUMBER_INVALID_TIP); } double unitPrice = getUnitPrice(menuNum); // 获取装修档次对应的单价 String unitPriceDesc = getPackageDesc(menuNum); // 获取装修档次对应的描述 // 非0就进行计算(获取装修金额) if (unitPrice > 0 && houseArea > 0) { double amount = quoteCalc(houseArea, unitPrice); // 展示数据 System.out.printf(printTitle); System.out.printf(printAreaTip + "%n", houseArea); System.out.printf(printLevelPackageTip + "%n", unitPriceDesc); System.out.printf(printLevelUnitPriceTip + "%n", unitPrice); System.out.printf(printLine); System.out.printf(printAmountTip + "%n", amount); } } } /** * 根据键盘输入来提取面积(m²) * * @param area * @return houseArea(退出就返回-1,空就返回-2,无效就返回-3,其他正常返回double) */ public static double getHouseArea(String area) { String areaRegex = "^[0-9]+(\\.[0-9]+)?$"; // 判断面积输入的正则表达式 double houseArea = INPUT_INVALID; // 面积变量的初始值设定为-3(无效输入) // 进行空判断 if (area.strip().isBlank()) { houseArea = INPUT_IS_BLANK; // 面积的返回值设定为-2(无输入) } // 非空的话就判断是否退出(exit),然后正则判断,并进行面积判断(必须大于0) if ("exit".equalsIgnoreCase(area)) { houseArea = INPUT_EXIT; // 面积的返回值设定为-1(退出程序) } else { if (area.strip().matches(areaRegex)) { houseArea = Double.parseDouble(area); } } return houseArea; } /** * 根据选择的菜单编号返回对应的装修档次的单价(元 / m²) * * @param menuNumber * @return unitPrice */ public static double getUnitPrice(int menuNumber) { return switch (menuNumber) { case 1 -> LEVEL_ECONOMY_UNIT_PRICE; // 经济套餐的单价 case 2 -> LEVEL_COMFORT_UNIT_PRICE; // 舒适套餐的单价 case 3 -> LEVEL_LUXURY_UNIT_PRICE; // 豪华套餐的单价 default -> 0; }; } /** * 根据选择的菜单编号返回对应的装修档次的描述 * * @param menuNumber * @return unitPriceDesc */ public static String getPackageDesc(int menuNumber) { return switch (menuNumber) { case 1 -> LEVEL_ECONOMY_DESC; // 经济套餐的描述 case 2 -> LEVEL_COMFORT_DESC; // 舒适套餐的描述 case 3 -> LEVEL_LUXURY_DESC; // 豪华套餐的描述 default -> ""; }; } /** * 获取装修档次装修套餐的菜单编号 * * @param selected * @return */ public static int getMenuNumber(String selected) { String priceRegex = "^[0123]$"; // 判断装修档次菜单编号输入的正则表达式 int menuNumber = INPUT_INVALID_MENU_NUMBER; if (selected.strip().isBlank()) { menuNumber = INPUT_IS_BLANK; } else { if (selected.strip().matches(priceRegex)) { // 正则判断selected的值为 0-3的数字,1-3为对应的套餐 int num = Integer.parseInt(selected); if (num > 0 && num < 3) { menuNumber = switch (num) { case 1 -> LEVEL_ECONOMY_MENU_NUMBER; // 经济套餐的菜单编号 case 2 -> LEVEL_COMFORT_MENU_NUMBER; // 舒适套餐的菜单编号 case 3 -> LEVEL_LUXURY_MENU_NUMBER; // 豪华套餐的菜单编号 default -> INPUT_INVALID_MENU_NUMBER; }; } } } return menuNumber; } /** * 金额(元) = 面积(m²) * 装修档次的单价(元 / m²) * * @param houseArea * @param unitPrice * @return houseArea * unitPrice(面积小于等于0就返回0,单价小于等于0就返回0) */ public static double quoteCalc(double houseArea, double unitPrice) { if (houseArea <= 0) { return 0; } if (unitPrice <= 0) { return 0; } return houseArea * unitPrice; } }
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
鱼友0258
下载 APP