Java面向对象实战从零构建租车系统的继承与多态设计租车系统是学习面向对象编程(OOP)的绝佳案例。这个看似简单的业务场景实际上涵盖了类设计、继承体系、多态应用等核心概念。我们将从零开始构建一个完整的租车系统重点讲解如何用Java实现优雅的面向对象设计。1. 系统分析与类设计在动手编码之前我们需要对租车业务进行充分分析。一个典型的租车系统包含以下核心要素车辆类型客车、货车、皮卡等不同车型租赁属性租金计算、租期管理载客/载货能力不同车型的运输特性业务规则费用计算、可用性检查等基于这些分析我们可以设计出以下类结构// 基类车辆 abstract class Vehicle { private String model; private double dailyRate; public Vehicle(String model, double dailyRate) { this.model model; this.dailyRate dailyRate; } public double calculateRentalFee(int days) { return days * dailyRate; } // 抽象方法子类必须实现 public abstract String getCapacityDescription(); } // 客车类 class PassengerCar extends Vehicle { private int passengerCapacity; public PassengerCar(String model, double dailyRate, int passengerCapacity) { super(model, dailyRate); this.passengerCapacity passengerCapacity; } Override public String getCapacityDescription() { return 载客量: passengerCapacity 人; } } // 货车类 class Truck extends Vehicle { private double cargoCapacity; // 吨 public Truck(String model, double dailyRate, double cargoCapacity) { super(model, dailyRate); this.cargoCapacity cargoCapacity; } Override public String getCapacityDescription() { return 载货量: cargoCapacity 吨; } } // 皮卡类 class PickupTruck extends Vehicle { private int passengerCapacity; private double cargoCapacity; public PickupTruck(String model, double dailyRate, int passengerCapacity, double cargoCapacity) { super(model, dailyRate); this.passengerCapacity passengerCapacity; this.cargoCapacity cargoCapacity; } Override public String getCapacityDescription() { return 载客量: passengerCapacity 人, 载货量: cargoCapacity 吨; } }2. 多态在租车系统中的应用多态是OOP的三大特性之一它允许我们以统一的方式处理不同类型的对象。在我们的租车系统中多态主要体现在统一接口所有车辆都继承自Vehicle基类动态绑定运行时确定调用哪个子类的方法扩展性新增车型不影响现有代码下面是一个展示多态优势的示例public class RentalSystem { private ListVehicle fleet new ArrayList(); public void initializeFleet() { fleet.add(new PassengerCar(商务轿车, 500, 5)); fleet.add(new Truck(厢式货车, 800, 3.5)); fleet.add(new PickupTruck(皮卡, 600, 4, 1.5)); } public void displayFleetInfo() { for (Vehicle vehicle : fleet) { System.out.println(vehicle.getModel() - vehicle.getCapacityDescription()); } } public double calculateTotalRental(Vehicle vehicle, int days) { return vehicle.calculateRentalFee(days); } }在这个设计中calculateTotalRental方法可以接受任何Vehicle子类的实例系统会自动调用正确的计算方法这就是多态的威力。3. 系统功能实现与业务逻辑现在我们来实现租车系统的核心业务逻辑。系统需要处理以下功能车辆选择与组合租期计算费用汇总载客/载货能力统计以下是核心业务类的实现public class RentalService { private ListVehicle availableVehicles; private ListRentalItem currentRental new ArrayList(); public RentalService(ListVehicle availableVehicles) { this.availableVehicles availableVehicles; } public void addToRental(int vehicleIndex, int days) { if (vehicleIndex 0 vehicleIndex availableVehicles.size()) { currentRental.add(new RentalItem(availableVehicles.get(vehicleIndex), days)); } } public RentalSummary calculateSummary() { int totalPassengers 0; double totalCargo 0.0; double totalCost 0.0; for (RentalItem item : currentRental) { Vehicle vehicle item.getVehicle(); int days item.getDays(); totalCost vehicle.calculateRentalFee(days); if (vehicle instanceof PassengerCar) { totalPassengers ((PassengerCar) vehicle).getPassengerCapacity() * days; } else if (vehicle instanceof Truck) { totalCargo ((Truck) vehicle).getCargoCapacity() * days; } else if (vehicle instanceof PickupTruck) { PickupTruck pickup (PickupTruck) vehicle; totalPassengers pickup.getPassengerCapacity() * days; totalCargo pickup.getCargoCapacity() * days; } } return new RentalSummary(totalPassengers, totalCargo, totalCost); } } class RentalItem { private Vehicle vehicle; private int days; public RentalItem(Vehicle vehicle, int days) { this.vehicle vehicle; this.days days; } // getters... } class RentalSummary { private int totalPassengers; private double totalCargo; private double totalCost; public RentalSummary(int totalPassengers, double totalCargo, double totalCost) { this.totalPassengers totalPassengers; this.totalCargo totalCargo; this.totalCost totalCost; } Override public String toString() { return String.format(总载客: %d人, 总载货: %.2f吨, 总费用: %.2f元, totalPassengers, totalCargo, totalCost); } }4. 用户交互与系统集成为了让系统真正可用我们需要实现用户交互层。这里我们采用控制台界面但设计上保持业务逻辑与界面分离便于未来扩展。public class RentalApp { private RentalService rentalService; private Scanner scanner; public RentalApp() { initializeVehicles(); this.scanner new Scanner(System.in); } private void initializeVehicles() { ListVehicle vehicles new ArrayList(); vehicles.add(new PassengerCar(商务轿车, 500, 5)); vehicles.add(new PassengerCar(中巴车, 800, 15)); vehicles.add(new Truck(小型货车, 600, 2.0)); vehicles.add(new Truck(大型货车, 1200, 10.0)); vehicles.add(new PickupTruck(标准皮卡, 450, 4, 1.5)); this.rentalService new RentalService(vehicles); } public void start() { displayWelcomeMessage(); displayVehicleList(); boolean renting true; while (renting) { System.out.print(\n请输入要租赁的车辆编号(0结束): ); int choice scanner.nextInt(); if (choice 0) { renting false; } else { System.out.print(请输入租赁天数: ); int days scanner.nextInt(); rentalService.addToRental(choice - 1, days); } } displayRentalSummary(); } private void displayWelcomeMessage() { System.out.println( 欢迎使用租车系统 ); System.out.println(以下是可租车辆列表:); } private void displayVehicleList() { ListVehicle vehicles rentalService.getAvailableVehicles(); for (int i 0; i vehicles.size(); i) { Vehicle v vehicles.get(i); System.out.printf(%d. %s - %s - 每日租金: %.2f元\n, i 1, v.getModel(), v.getCapacityDescription(), v.getDailyRate()); } } private void displayRentalSummary() { RentalSummary summary rentalService.calculateSummary(); System.out.println(\n 租赁汇总 ); System.out.println(summary); } public static void main(String[] args) { new RentalApp().start(); } }5. 高级主题与系统扩展我们的基础系统已经完成但一个真正的商业系统还需要考虑更多因素。以下是几个可能的扩展方向5.1 价格策略模式不同车型、不同租期可能有不同的计价策略。我们可以使用策略模式来实现灵活的价格计算interface PricingStrategy { double calculatePrice(double baseRate, int days); } class StandardPricing implements PricingStrategy { public double calculatePrice(double baseRate, int days) { return baseRate * days; } } class WeeklyDiscountPricing implements PricingStrategy { public double calculatePrice(double baseRate, int days) { int weeks days / 7; int remainingDays days % 7; return (weeks * baseRate * 6) (remainingDays * baseRate); } } class Vehicle { private PricingStrategy pricingStrategy new StandardPricing(); public void setPricingStrategy(PricingStrategy strategy) { this.pricingStrategy strategy; } public double calculateRentalFee(int days) { return pricingStrategy.calculatePrice(dailyRate, days); } }5.2 车辆状态管理实际租车系统中车辆可能有多种状态可用、维修中、已租出等。我们可以引入状态模式interface VehicleState { boolean isAvailable(); VehicleState rent(); VehicleState returnVehicle(); VehicleState sendForMaintenance(); } class AvailableState implements VehicleState { public boolean isAvailable() { return true; } public VehicleState rent() { return new RentedState(); } // 其他方法实现... } class Vehicle { private VehicleState state new AvailableState(); public boolean isAvailable() { return state.isAvailable(); } public void rent() { state state.rent(); } }5.3 数据库集成与持久化实际应用中车辆数据应该存储在数据库中。我们可以使用JDBC或JPA来实现Entity Inheritance(strategy InheritanceType.SINGLE_TABLE) DiscriminatorColumn(name vehicle_type) public abstract class Vehicle { Id GeneratedValue private Long id; private String model; private double dailyRate; // ... } Entity DiscriminatorValue(PASSENGER) public class PassengerCar extends Vehicle { private int passengerCapacity; // ... } public class VehicleRepository { PersistenceContext private EntityManager em; public ListVehicle findAllAvailable() { return em.createQuery( SELECT v FROM Vehicle v WHERE v.available true, Vehicle.class) .getResultList(); } }6. 测试与验证完善的测试是保证系统质量的关键。我们可以为系统编写单元测试和集成测试public class RentalServiceTest { private RentalService rentalService; Before public void setUp() { ListVehicle vehicles Arrays.asList( new PassengerCar(Test Car, 100, 4), new Truck(Test Truck, 200, 2.0) ); rentalService new RentalService(vehicles); } Test public void testPassengerCarRental() { rentalService.addToRental(0, 3); // 租用客车3天 RentalSummary summary rentalService.calculateSummary(); assertEquals(12, summary.getTotalPassengers()); // 4人×3天 assertEquals(0.0, summary.getTotalCargo(), 0.01); assertEquals(300.0, summary.getTotalCost(), 0.01); } Test public void testMixedRental() { rentalService.addToRental(0, 2); // 客车2天 rentalService.addToRental(1, 1); // 货车1天 RentalSummary summary rentalService.calculateSummary(); assertEquals(8, summary.getTotalPassengers()); // 4人×2天 assertEquals(2.0, summary.getTotalCargo(), 0.01); // 2吨×1天 assertEquals(400.0, summary.getTotalCost(), 0.01); // 100×2 200×1 } }在实际项目中我们还会考虑添加日志记录、异常处理、输入验证等功能使系统更加健壮。
Java面向对象实战:手把手教你用继承和多态打造租车系统(附完整代码)
Java面向对象实战从零构建租车系统的继承与多态设计租车系统是学习面向对象编程(OOP)的绝佳案例。这个看似简单的业务场景实际上涵盖了类设计、继承体系、多态应用等核心概念。我们将从零开始构建一个完整的租车系统重点讲解如何用Java实现优雅的面向对象设计。1. 系统分析与类设计在动手编码之前我们需要对租车业务进行充分分析。一个典型的租车系统包含以下核心要素车辆类型客车、货车、皮卡等不同车型租赁属性租金计算、租期管理载客/载货能力不同车型的运输特性业务规则费用计算、可用性检查等基于这些分析我们可以设计出以下类结构// 基类车辆 abstract class Vehicle { private String model; private double dailyRate; public Vehicle(String model, double dailyRate) { this.model model; this.dailyRate dailyRate; } public double calculateRentalFee(int days) { return days * dailyRate; } // 抽象方法子类必须实现 public abstract String getCapacityDescription(); } // 客车类 class PassengerCar extends Vehicle { private int passengerCapacity; public PassengerCar(String model, double dailyRate, int passengerCapacity) { super(model, dailyRate); this.passengerCapacity passengerCapacity; } Override public String getCapacityDescription() { return 载客量: passengerCapacity 人; } } // 货车类 class Truck extends Vehicle { private double cargoCapacity; // 吨 public Truck(String model, double dailyRate, double cargoCapacity) { super(model, dailyRate); this.cargoCapacity cargoCapacity; } Override public String getCapacityDescription() { return 载货量: cargoCapacity 吨; } } // 皮卡类 class PickupTruck extends Vehicle { private int passengerCapacity; private double cargoCapacity; public PickupTruck(String model, double dailyRate, int passengerCapacity, double cargoCapacity) { super(model, dailyRate); this.passengerCapacity passengerCapacity; this.cargoCapacity cargoCapacity; } Override public String getCapacityDescription() { return 载客量: passengerCapacity 人, 载货量: cargoCapacity 吨; } }2. 多态在租车系统中的应用多态是OOP的三大特性之一它允许我们以统一的方式处理不同类型的对象。在我们的租车系统中多态主要体现在统一接口所有车辆都继承自Vehicle基类动态绑定运行时确定调用哪个子类的方法扩展性新增车型不影响现有代码下面是一个展示多态优势的示例public class RentalSystem { private ListVehicle fleet new ArrayList(); public void initializeFleet() { fleet.add(new PassengerCar(商务轿车, 500, 5)); fleet.add(new Truck(厢式货车, 800, 3.5)); fleet.add(new PickupTruck(皮卡, 600, 4, 1.5)); } public void displayFleetInfo() { for (Vehicle vehicle : fleet) { System.out.println(vehicle.getModel() - vehicle.getCapacityDescription()); } } public double calculateTotalRental(Vehicle vehicle, int days) { return vehicle.calculateRentalFee(days); } }在这个设计中calculateTotalRental方法可以接受任何Vehicle子类的实例系统会自动调用正确的计算方法这就是多态的威力。3. 系统功能实现与业务逻辑现在我们来实现租车系统的核心业务逻辑。系统需要处理以下功能车辆选择与组合租期计算费用汇总载客/载货能力统计以下是核心业务类的实现public class RentalService { private ListVehicle availableVehicles; private ListRentalItem currentRental new ArrayList(); public RentalService(ListVehicle availableVehicles) { this.availableVehicles availableVehicles; } public void addToRental(int vehicleIndex, int days) { if (vehicleIndex 0 vehicleIndex availableVehicles.size()) { currentRental.add(new RentalItem(availableVehicles.get(vehicleIndex), days)); } } public RentalSummary calculateSummary() { int totalPassengers 0; double totalCargo 0.0; double totalCost 0.0; for (RentalItem item : currentRental) { Vehicle vehicle item.getVehicle(); int days item.getDays(); totalCost vehicle.calculateRentalFee(days); if (vehicle instanceof PassengerCar) { totalPassengers ((PassengerCar) vehicle).getPassengerCapacity() * days; } else if (vehicle instanceof Truck) { totalCargo ((Truck) vehicle).getCargoCapacity() * days; } else if (vehicle instanceof PickupTruck) { PickupTruck pickup (PickupTruck) vehicle; totalPassengers pickup.getPassengerCapacity() * days; totalCargo pickup.getCargoCapacity() * days; } } return new RentalSummary(totalPassengers, totalCargo, totalCost); } } class RentalItem { private Vehicle vehicle; private int days; public RentalItem(Vehicle vehicle, int days) { this.vehicle vehicle; this.days days; } // getters... } class RentalSummary { private int totalPassengers; private double totalCargo; private double totalCost; public RentalSummary(int totalPassengers, double totalCargo, double totalCost) { this.totalPassengers totalPassengers; this.totalCargo totalCargo; this.totalCost totalCost; } Override public String toString() { return String.format(总载客: %d人, 总载货: %.2f吨, 总费用: %.2f元, totalPassengers, totalCargo, totalCost); } }4. 用户交互与系统集成为了让系统真正可用我们需要实现用户交互层。这里我们采用控制台界面但设计上保持业务逻辑与界面分离便于未来扩展。public class RentalApp { private RentalService rentalService; private Scanner scanner; public RentalApp() { initializeVehicles(); this.scanner new Scanner(System.in); } private void initializeVehicles() { ListVehicle vehicles new ArrayList(); vehicles.add(new PassengerCar(商务轿车, 500, 5)); vehicles.add(new PassengerCar(中巴车, 800, 15)); vehicles.add(new Truck(小型货车, 600, 2.0)); vehicles.add(new Truck(大型货车, 1200, 10.0)); vehicles.add(new PickupTruck(标准皮卡, 450, 4, 1.5)); this.rentalService new RentalService(vehicles); } public void start() { displayWelcomeMessage(); displayVehicleList(); boolean renting true; while (renting) { System.out.print(\n请输入要租赁的车辆编号(0结束): ); int choice scanner.nextInt(); if (choice 0) { renting false; } else { System.out.print(请输入租赁天数: ); int days scanner.nextInt(); rentalService.addToRental(choice - 1, days); } } displayRentalSummary(); } private void displayWelcomeMessage() { System.out.println( 欢迎使用租车系统 ); System.out.println(以下是可租车辆列表:); } private void displayVehicleList() { ListVehicle vehicles rentalService.getAvailableVehicles(); for (int i 0; i vehicles.size(); i) { Vehicle v vehicles.get(i); System.out.printf(%d. %s - %s - 每日租金: %.2f元\n, i 1, v.getModel(), v.getCapacityDescription(), v.getDailyRate()); } } private void displayRentalSummary() { RentalSummary summary rentalService.calculateSummary(); System.out.println(\n 租赁汇总 ); System.out.println(summary); } public static void main(String[] args) { new RentalApp().start(); } }5. 高级主题与系统扩展我们的基础系统已经完成但一个真正的商业系统还需要考虑更多因素。以下是几个可能的扩展方向5.1 价格策略模式不同车型、不同租期可能有不同的计价策略。我们可以使用策略模式来实现灵活的价格计算interface PricingStrategy { double calculatePrice(double baseRate, int days); } class StandardPricing implements PricingStrategy { public double calculatePrice(double baseRate, int days) { return baseRate * days; } } class WeeklyDiscountPricing implements PricingStrategy { public double calculatePrice(double baseRate, int days) { int weeks days / 7; int remainingDays days % 7; return (weeks * baseRate * 6) (remainingDays * baseRate); } } class Vehicle { private PricingStrategy pricingStrategy new StandardPricing(); public void setPricingStrategy(PricingStrategy strategy) { this.pricingStrategy strategy; } public double calculateRentalFee(int days) { return pricingStrategy.calculatePrice(dailyRate, days); } }5.2 车辆状态管理实际租车系统中车辆可能有多种状态可用、维修中、已租出等。我们可以引入状态模式interface VehicleState { boolean isAvailable(); VehicleState rent(); VehicleState returnVehicle(); VehicleState sendForMaintenance(); } class AvailableState implements VehicleState { public boolean isAvailable() { return true; } public VehicleState rent() { return new RentedState(); } // 其他方法实现... } class Vehicle { private VehicleState state new AvailableState(); public boolean isAvailable() { return state.isAvailable(); } public void rent() { state state.rent(); } }5.3 数据库集成与持久化实际应用中车辆数据应该存储在数据库中。我们可以使用JDBC或JPA来实现Entity Inheritance(strategy InheritanceType.SINGLE_TABLE) DiscriminatorColumn(name vehicle_type) public abstract class Vehicle { Id GeneratedValue private Long id; private String model; private double dailyRate; // ... } Entity DiscriminatorValue(PASSENGER) public class PassengerCar extends Vehicle { private int passengerCapacity; // ... } public class VehicleRepository { PersistenceContext private EntityManager em; public ListVehicle findAllAvailable() { return em.createQuery( SELECT v FROM Vehicle v WHERE v.available true, Vehicle.class) .getResultList(); } }6. 测试与验证完善的测试是保证系统质量的关键。我们可以为系统编写单元测试和集成测试public class RentalServiceTest { private RentalService rentalService; Before public void setUp() { ListVehicle vehicles Arrays.asList( new PassengerCar(Test Car, 100, 4), new Truck(Test Truck, 200, 2.0) ); rentalService new RentalService(vehicles); } Test public void testPassengerCarRental() { rentalService.addToRental(0, 3); // 租用客车3天 RentalSummary summary rentalService.calculateSummary(); assertEquals(12, summary.getTotalPassengers()); // 4人×3天 assertEquals(0.0, summary.getTotalCargo(), 0.01); assertEquals(300.0, summary.getTotalCost(), 0.01); } Test public void testMixedRental() { rentalService.addToRental(0, 2); // 客车2天 rentalService.addToRental(1, 1); // 货车1天 RentalSummary summary rentalService.calculateSummary(); assertEquals(8, summary.getTotalPassengers()); // 4人×2天 assertEquals(2.0, summary.getTotalCargo(), 0.01); // 2吨×1天 assertEquals(400.0, summary.getTotalCost(), 0.01); // 100×2 200×1 } }在实际项目中我们还会考虑添加日志记录、异常处理、输入验证等功能使系统更加健壮。