一、案例背景:机票价格计算需求
核心业务规则
- 旺季(5-10月)
🔹 头等舱:原价 × 90%
🔹 经济舱:原价 × 85% - 淡季(1-4月、11-12月)
🔹 头等舱:原价 × 70%
🔹 经济舱:原价 × 65% - 输入约束
🔸 月份:1-12的整数
🔸 舱位类型:仅支持"头等舱"/"经济舱"
🔸 原价:正数(支持小数)
二、代码全景解析(优化版)
package com.insightfuture.test;
import java.util.Scanner;
public class BuyPlaneTickets {
// 定义常量折扣率
private static final double HIGH_SEASON_FIRST_CLASS = 0.9;
private static final double HIGH_SEASON_ECONOMY = 0.85;
private static final double LOW_SEASON_FIRST_CLASS = 0.7;
private static final double LOW_SEASON_ECONOMY = 0.65;
public static void main(String[] MakeItPossible) {
Scanner sc = new Scanner(System.in);
int month;
String type;
double originalPrice;
double price = -1;
// 输入月份并验证
while (true) {
System.out.println("请输入月份(1-12):");
month = sc.nextInt();
if (month >= 1 && month <= 12) break;
System.out.println("月份无效,请重新输入!");
}
// 输入座位类型并验证
while (true) {
System.out.println("请输入座位类型(头等舱/经济舱):");
type = sc.next();
if (type.equals("头等舱") || type.equals("经济舱")) break;
System.out.println("座位类型无效,请重新输入!");
}
// 输入原价
System.out.println("请输入原价:");
originalPrice = sc.nextDouble();
// 计算折扣价
if (month >= 5 && month <= 10) {
// 旺季
price = getPrice(type, price, originalPrice, HIGH_SEASON_FIRST_CLASS, HIGH_SEASON_ECONOMY);
} else {
// 淡季
price = getPrice(type, price, originalPrice, LOW_SEASON_FIRST_CLASS, LOW_SEASON_ECONOMY);
}
System.out.println(month + "月份" + type + "机票原价:" + originalPrice + "元,折扣后价格为:" + price);
}
/*
getPrice方法:根据条件规则计算后的实际价格
*/
private static double getPrice(String type, double price, double originalPrice, double highSeasonFirstClass, double highSeasonEconomy) {
switch (type) {
case "头等舱":
price = originalPrice * highSeasonFirstClass;
break;
case "经济舱":
price = originalPrice * highSeasonEconomy;
break;
}
return price;
}
}
三、四大核心优化策略
1. 防御式输入验证体系
验证类型 | 实现方式 | 防御效果 |
---|---|---|
月份验证 | while循环 + 范围判断 | 杜绝13月等非法值 |
舱位验证 | 白名单校验(equals ) | 过滤"商务舱"等无效输入 |
价格验证 | Scanner.nextDouble() | 兼容小数输入 |
// 舱位类型验证示例
private static String validateType(Scanner sc) {
while (true) {
System.out.print("请输入舱位(头等舱/经济舱): ");
String input = sc.next();
if (input.equals("头等舱") || input.equals("经济舱")) {
return input;
}
System.out.println("⚠️ 舱位类型错误!");
}
}
2. 魔法值消除术
优化对比表:
代码版本 | 折扣率代码示例 | 可维护性 | 可读性 |
---|---|---|---|
原始版本 | price * 0.9 | ❌ | ❌ |
优化版 | price * HIGH_SEASON_FIRST | ✅ | ✅ |
常量命名技巧:
- 季节标识(
HIGH/LOW_SEASON
) - 舱位类型(
FIRST/ECONOMY
) - 语义化组合 → 一眼看懂业务含义
3. 计算逻辑分层封装
模块化设计图解:
main()
│
├─输入验证层───validateMonth()
│ ├─validateType()
│ └─validatePrice()
│
└─业务计算层───calculateFinalPrice()
├─季节判断
└─舱位费率匹配
方法设计原则:
- 单一职责:每个方法只做一件事
- 开闭原则:新增舱位不改动主逻辑
4. 专业级输出优化
// 原始输出
System.out.println("5月份经济舱价格...");
// 优化后输出
System.out.printf("[%02d月] %s 原价: ¥%.2f → 折后价: ¥%.2f%n",
month, type, price, finalPrice);
优化点:
%02d
:月份统一显示为两位数(如"05月")%.2f
:价格强制保留两位小数¥
符号:符合财务规范
四、扩展空间与高阶优化方向
1. 精度问题解决方案
金融计算致命陷阱:
// 错误示例:double计算
0.1 + 0.2 = 0.30000000000000004
// 正确方案:BigDecimal
BigDecimal price = new BigDecimal("1000.00");
BigDecimal result = price.multiply(new BigDecimal("0.9"));
2. 设计模式改造
策略模式应用场景:
// 定义策略接口
interface DiscountStrategy {
double getFirstClassRate();
double getEconomyRate();
}
// 实现具体策略
class HighSeasonStrategy implements DiscountStrategy {
public double getFirstClassRate() { return 0.9; }
public double getEconomyRate() { return 0.85; }
}
五、新手常见误区指南
误区1:过度信任用户输入
反面教材:
// 直接使用未验证的输入
int month = sc.nextInt();
calculatePrice(month, type, price); // 若month=13会怎样?
正确认知:所有外部输入都可能是恶意的!
误区2:复制粘贴的代价
代码坏味道:
if (month >=5 && month <=10) {
// 计算旺季价格
} else {
// 计算淡季价格(重复相同switch结构)
}
重构建议:提取费率配置到Map结构
Map<String, Double> rates = isHighSeason ? highSeasonRates : lowSeasonRates;
return price * rates.get(type);
六、实战总结
关键收获清单
- 🛡️ 防御式编程:输入验证是系统的第一道防线
- 🧩 模块化设计:拒绝意大利面条式代码
- 📚 常量管理:让魔法数字无处遁形
- 💡 可扩展思维:写出适应变化的代码
#Java #代码优化 #防御式编程 #实战教程