Menu
CoddyTech

Dịch vụ cho thuê phương tiện

Thuộc phần Lập trình hướng đối tượng trong hành trình C# của Coddy. Bài học 70 trên 70.

challenge icon

Thử thách

Dễ

Hãy cùng xây dựng một dịch vụ cho thuê phương tiện, kết hợp tính kế thừa, giao diện và mẫu Strategy! Bạn sẽ tạo một hệ thống cho phép thuê nhiều loại phương tiện khác nhau bằng các chiến lược định giá linh hoạt, qua đó cho thấy OOP giúp xây dựng logic nghiệp vụ dễ bảo trì và mở rộng như thế nào.

Bạn sẽ sắp xếp code trong sáu tệp:

  • Vehicle.cs: Tạo hệ thống phân cấp phương tiện trong không gian tên Rental.Models. Lớp cơ sở Vehicle cần có các thuộc tính chỉ đọc LicensePlate và Brand, thuộc tính DailyRate (decimal) và thuộc tính IsAvailable có bộ thiết lập riêng, được điều khiển thông qua các phương thức MarkAsRented() và MarkAsReturned(). Sau đó, tạo ba lớp dẫn xuất: Car với thuộc tính Seats, Motorcycle với thuộc tính EngineCC và Truck với thuộc tính CargoCapacity (decimal). Mỗi lớp dẫn xuất cần gọi hàm khởi tạo của lớp cơ sở và thiết lập thuộc tính riêng của lớp đó.
  • IPricingStrategy.cs: Định nghĩa giao diện IPricingStrategy trong không gian tên Rental.Pricing, với một phương thức duy nhất là CalculatePrice(Vehicle vehicle, int days), trả về một giá trị decimal.
  • PricingStrategies.cs: Triển khai hai chiến lược định giá trong không gian tên Rental.Pricing. StandardPricing chỉ cần nhân đơn giá hằng ngày của phương tiện với số ngày. WeekendDiscountPricing giảm giá 10% (nhân với 0.9) nếu thời gian thuê từ 2 ngày trở lên, nếu không thì áp dụng cách tính tiêu chuẩn.
  • RentalRecord.cs: Tạo lớp Rental trong không gian tên Rental.Models để theo dõi các lượt thuê. Lớp này cần có các thuộc tính chỉ đọc CustomerName (string), Vehicle (Vehicle), Days (int) và TotalPrice (decimal), tất cả được thiết lập thông qua hàm khởi tạo.
  • RentalService.cs: Tạo lớp RentalService trong không gian tên Rental.Services để quản lý đội xe và xử lý việc cho thuê. Lớp này nhận một IPricingStrategy thông qua hàm khởi tạo (tiêm phụ thuộc). Hãy triển khai:
    • AddVehicle(Vehicle vehicle) - thêm một phương tiện vào đội xe
    • RentVehicle(string customerName, string licensePlate, int days) - trả về một đối tượng Rental nếu phương tiện tồn tại và sẵn sàng cho thuê, nếu không thì trả về null. Nhớ đánh dấu phương tiện là đã cho thuê và tính giá bằng chiến lược được tiêm vào.
    • ReturnVehicle(string licensePlate) - đánh dấu phương tiện là sẵn sàng, trả về true nếu thao tác thành công
    • GetAvailableVehicles() - trả về danh sách tất cả phương tiện đang sẵn sàng
  • Program.cs: Kết hợp mọi thứ bằng cách tạo phương tiện, thiết lập dịch vụ với một chiến lược định giá và xử lý các thao tác thuê dựa trên đầu vào.

Bạn sẽ nhận các đầu vào sau:

  • Chiến lược định giá cần dùng (standard hoặc weekend)
  • Số lượng phương tiện cần thêm
  • Với mỗi phương tiện: loại (car, motorcycle hoặc truck), biển số, nhãn hiệu, đơn giá hằng ngày và giá trị riêng theo loại (số ghế, engineCC hoặc sức chứa hàng)
  • Số lượng thao tác cần thực hiện
  • Với mỗi thao tác: hành động, theo sau là dữ liệu liên quan

Định dạng thao tác:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

Định dạng đầu ra:

  • Thuê thành công: Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • Thuê thất bại: Rental failed: {licensePlate}
  • Trả xe thành công: Returned: {licensePlate}
  • Trả xe thất bại: Return failed: {licensePlate}
  • Phương tiện sẵn sàng: In từng phương tiện sẵn sàng theo định dạng {Type}: {Brand} ({LicensePlate}) - {DailyRate}/day, trong đó Type là "Car", "Motorcycle" hoặc "Truck"

Ví dụ, nếu đầu vào là:

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

Đầu ra sẽ là:

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

Hãy chú ý cách chiến lược định giá được tiêm vào dịch vụ. Bạn có thể dễ dàng thay StandardPricing bằng WeekendDiscountPricing mà không cần thay đổi code của RentalService. Đây chính là sức mạnh của mẫu Strategy kết hợp với tiêm phụ thuộc!

Tự làm thử

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

class Program
{
    public static void Main(string[] args)
    {
        // Đọc loại chiến lược định giá
        string strategyType = Console.ReadLine();
        
        // TODO: Tạo chiến lược định giá phù hợp dựa trên đầu vào
        // "standard" -> StandardPricing
        // "weekend" -> WeekendDiscountPricing
        IPricingStrategy strategy = null; // TODO: Khởi tạo dựa trên strategyType
        
        // TODO: Tạo RentalService với chiến lược định giá
        
        // Đọc số lượng xe
        int vehicleCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Đọc và thêm từng xe vào dịch vụ
        // Với mỗi xe, đọc:
        // - loại (ô tô, xe máy, xe tải)
        // - biển số xe
        // - hãng xe
        // - giá thuê hằng ngày
        // - giá trị riêng theo loại xe (số ghế, engineCC hoặc sức chứa hàng)
        
        // Đọc số lượng thao tác
        int operationCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Xử lý từng thao tác
        // Các thao tác: rent, return, available
        // 
        // Với "rent":
        //   Đọc customerName, licensePlate, days
        //   Đầu ra: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
        //   Hoặc: "Rental failed: {licensePlate}"
        //
        // Với "return":
        //   Đọc licensePlate
        //   Đầu ra: "Returned: {licensePlate}" hoặc "Return failed: {licensePlate}"
        //
        // Với "available":
        //   In ra từng xe còn trống theo định dạng:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C# online