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.
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ênRental.Models. Lớp cơ sởVehiclecần có các thuộc tính chỉ đọcLicensePlatevàBrand, thuộc tínhDailyRate(decimal) và thuộc tínhIsAvailablecó bộ thiết lập riêng, được điều khiển thông qua các phương thứcMarkAsRented()vàMarkAsReturned(). Sau đó, tạo ba lớp dẫn xuất:Carvới thuộc tínhSeats,Motorcyclevới thuộc tínhEngineCCvàTruckvới thuộc tínhCargoCapacity(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ệnIPricingStrategytrong không gian tênRental.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ênRental.Pricing.StandardPricingchỉ cần nhân đơn giá hằng ngày của phương tiện với số ngày.WeekendDiscountPricinggiả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ớpRentaltrong không gian tênRental.Modelsđể theo dõi các lượt thuê. Lớp này cần có các thuộc tính chỉ đọcCustomerName(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ớpRentalServicetrong không gian tênRental.Servicesđể quản lý đội xe và xử lý việc cho thuê. Lớp này nhận mộtIPricingStrategythô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 xeRentVehicle(string customerName, string licensePlate, int days)- trả về một đối tượngRentalnế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ềtruenếu thao tác thành côngGetAvailableVehicles()- 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 (
standardhoặcweekend) - Số lượng phương tiện cần thêm
- Với mỗi phương tiện: loại (
car,motorcyclehoặctruck), 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-123Hã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
1Các khái niệm cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiKhông gian tên và chỉ thịGiới thiệu về lớp và đối tượngTừ khóa thisPhương thức và tham sốTrường và thuộc tínhHàm khởi tạoKhởi tạo đối tượngÔn tập: Máy tính đơn giản4Kế thừa
Cú pháp kế thừa cơ bản (:)Từ khóa 'base'Từ khóa virtual và overrideLớp sealedLớp cơ sở 'object'Ôn tập: hệ phân cấp nhân viên7Tính năng nâng cao
Nạp chồng toán tửBộ lập chỉ mục (this[])Ghi đè ToString()Phương thức mở rộngÔn tập: Danh sách tùy chỉnh10Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếSingleton an toàn với luồngMẫu FactoryMẫu Observer (sự kiện)Mẫu Strategy13Thử thách cuối
Nền tảng học trực tuyếnThành phần nhân vật trong trò chơiDịch vụ cho thuê phương tiện2Thuộc tính và thành viên tĩnh
Thuộc tính tự độngThuộc tính chỉ đọc hoặc chỉ ghiTrường và phương thức tĩnhLớp tĩnhThành viên có thân biểu thức5Đa hình và interface
Đa hình lúc biên dịch và lúc chạyInterface và lớp trừu tượngNhiều interfaceInterface tường minhUpcasting và downcastingÔn tập: bộ tính toán hình học8Các khái niệm OOP nâng cao
Ưu tiên composition hơn kế thừaGenerics (lớp và phương thức)Delegate và sự kiệnAttribute và reflectionGiao diện IDisposable và câu lệnh usingKiến thức cơ bản về dependency injection11Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổ hợpTự luyện tập: Trình biên dịch C# online