车辆租赁服务
本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 70 课,共 70 课。
挑战
简单让我们构建一个车辆租赁服务,把继承、接口和策略模式结合起来!你将创建一个系统,可以使用灵活的定价策略租赁不同类型的车辆,展示面向对象编程如何帮助构建易于维护和扩展的业务逻辑。
你需要将代码分到 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):将车辆标记为可用,成功时返回trueGetAvailableVehicles():返回所有可用车辆的列表
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# 在线编译器