Menu
CoddyTech

车辆租赁服务

本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 70 课,共 70 课。

challenge icon

挑战

简单

让我们构建一个车辆租赁服务,把继承、接口和策略模式结合起来!你将创建一个系统,可以使用灵活的定价策略租赁不同类型的车辆,展示面向对象编程如何帮助构建易于维护和扩展的业务逻辑。

你需要将代码分到 6 个文件中:

  • Vehicle.cs:在 Rental.Models 命名空间中创建车辆类层次结构。基类 Vehicle 应包含只读的 LicensePlate 和 Brand 属性、一个 DailyRate(decimal)属性,以及一个包含私有 setter 的 IsAvailable 属性,并通过 MarkAsRented() 和 MarkAsReturned() 方法控制其值。然后创建 3 个派生类:包含 Seats 属性的 Car、包含 EngineCC 属性的 Motorcycle,以及包含 CargoCapacity(decimal)属性的 Truck。每个派生类都应调用基类构造函数,并设置自己的属性。
  • IPricingStrategy.cs:在 Rental.Pricing 命名空间中定义 IPricingStrategy 接口,其中包含一个方法 CalculatePrice(Vehicle vehicle, int days),该方法返回 decimal。
  • PricingStrategies.cs:在 Rental.Pricing 命名空间中实现两种定价策略。StandardPricing 直接将车辆的日租金乘以租赁天数。WeekendDiscountPricing 会在租赁 2 天或更久时打 9 折(乘以 0.9),否则使用标准计算方式。
  • RentalRecord.cs:在 Rental.Models 命名空间中创建一个 Rental 类,用于跟踪租赁记录。它应包含只读属性 CustomerName(string)、Vehicle(Vehicle)、Days(int)和 TotalPrice(decimal),并通过构造函数设置这些属性。
  • RentalService.cs:在 Rental.Services 命名空间中创建一个 RentalService 类,用于管理车队和处理租赁。它通过构造函数接收一个 IPricingStrategy(依赖注入)。实现以下方法:
    • AddVehicle(Vehicle vehicle):将车辆添加到车队
    • RentVehicle(string customerName, string licensePlate, int days):如果车辆存在且可租赁,则返回一个 Rental 对象,否则返回 null。记得将车辆标记为已租出,并使用注入的策略计算价格。
    • ReturnVehicle(string licensePlate):将车辆标记为可用,成功时返回 true
    • GetAvailableVehicles():返回所有可用车辆的列表
  • Program.cs:整合所有内容,创建车辆、设置包含定价策略的服务,并根据输入处理租赁操作。

你将收到以下输入:

  • 要使用的定价策略(standard 或 weekend)
  • 要添加的车辆数量
  • 每辆车的信息:类型(car、motorcycle 或 truck)、车牌号、品牌、日租金,以及该类型对应的值(座位数、engineCC 或货物容量)
  • 要执行的操作数量
  • 每项操作:操作名称及相关数据

操作格式:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

输出格式:

  • 租赁成功:Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • 租赁失败:Rental failed: {licensePlate}
  • 归还成功:Returned: {licensePlate}
  • 归还失败:Return failed: {licensePlate}
  • 可用车辆:将每辆可用车辆按 {Type}: {Brand} ({LicensePlate}) - {DailyRate}/day 的格式输出,其中 Type 为 "Car"、"Motorcycle" 或 "Truck"

例如,如果输入为:

weekend
3
car
ABC-123
Toyota
50
5
motorcycle
XYZ-789
Honda
30
600
truck
TRK-001
Ford
80
2000
5
available
rent
Alice
ABC-123
3
rent
Bob
ABC-123
2
available
return
ABC-123

输出应为:

Car: Toyota (ABC-123) - 50/day
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Rented: Toyota (ABC-123) to Alice for 3 days - Total: 135.0
Rental failed: ABC-123
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Returned: ABC-123

注意,定价策略是注入到服务中的,因此你可以轻松地将 StandardPricing 换成 WeekendDiscountPricing,而无需更改 RentalService 代码。这就是策略模式与依赖注入结合的优势!

亲手试试

using System;
using System.Collections.Generic;
using Rental.Models;
using Rental.Pricing;
using Rental.Services;

class Program
{
    public static void Main(string[] args)
    {
        // 读取定价策略类型
        string strategyType = Console.ReadLine();
        
        // TODO: 根据输入创建合适的定价策略
        // "standard" -> StandardPricing
        // "weekend" -> WeekendDiscountPricing
        IPricingStrategy strategy = null; // TODO: 根据 strategyType 初始化
        
        // TODO: 使用定价策略创建 RentalService
        
        // 读取车辆数量
        int vehicleCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: 读取每辆车并将其添加到服务中
        // 读取每辆车的以下信息:
        // 类型(car、motorcycle、truck)
        // 车牌号
        // 品牌
        // - 每日租金
        // - 车型特有的值(座位数、engineCC 或载货容量)
        
        // 读取操作数量
        int operationCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: 处理每项操作
        // 操作类型:rent、return、available
        // 
        // 对于 "rent":
        //   读取 customerName、licensePlate 和 days
        //   输出:"Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
        //   或者:"Rental failed: {licensePlate}"
        //
        // 对于 "return":
        //   读取 licensePlate
        //   输出:"Returned: {licensePlate}" 或 "Return failed: {licensePlate}"
        //
        // 对于 "available":
        //   按以下格式输出每辆可用车辆:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

面向对象编程中的所有课

自己练习: C# 在线编译器