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 Java của Coddy. Bài học 87 trên 87.

Trong thử thách cuối cùng này, bạn sẽ xây dựng hệ thống Dịch vụ cho thuê phương tiện, kết hợp tất cả các khái niệm OOP mà bạn đã nắm vững trong khóa học này.

Hệ thống của bạn nên mô hình hóa một đội xe gồm nhiều loại phương tiện khác nhau. Hãy xem xét một lớp (class) cơ sở Vehicle với các thuộc tính chung như biển số, thương hiệu và giá thuê hằng ngày. Các lớp con như Car, Motorcycle và Truck có thể bổ sung các thuộc tính riêng như số ghế, dung tích động cơ hoặc sức chứa hàng hóa.

Giao diện có thể định nghĩa các hành vi cho thuê: giao diện Rentable có thể khai báo các phương thức như rent(), returnVehicle() và calculateCost(int days). Các loại phương tiện khác nhau có thể triển khai chiến lược định giá theo cách khác nhau, khiến đây trở thành trường hợp sử dụng hoàn hảo cho tính đa hình.

Hãy nghĩ xem lớp RentalAgency quản lý đội xe bằng cách sử dụng tính kết hợp như thế nào.

Các ngoại lệ tùy chỉnh như VehicleNotAvailableException có thể xử lý các trường hợp đặc biệt.

Bạn có thể áp dụng mẫu Factory để tạo phương tiện hoặc dùng enum cho loại phương tiện và trạng thái thuê.

Thử thách này kiểm tra khả năng thiết kế một hệ thống OOP hoàn chỉnh, có cấu trúc tốt của bạn. Chúc bạn may mắn!

challenge icon

Thử thách

Dễ

Hãy xây dựng một dịch vụ cho thuê xe hoàn chỉnh, kết hợp mọi thứ bạn đã học về lập trình hướng đối tượng! Bạn sẽ tạo một hệ thống quản lý đội xe gồm nhiều loại xe khác nhau, xử lý việc thuê xe với bước xác thực phù hợp và dùng mẫu thiết kế factory để tạo xe.

Bạn sẽ sắp xếp code trong bảy tệp:

  • RentalStatus.java: Tạo một enum biểu thị trạng thái thuê của xe. Thêm các giá trị AVAILABLE, RENTED và MAINTENANCE. Thêm trường riêng tư description (String), một hàm khởi tạo và một phương thức getter. Trạng thái khả dụng có phần mô tả "ready to rent", trạng thái đã thuê có phần mô tả "currently in use", còn trạng thái bảo dưỡng có phần mô tả "under service".
  • VehicleNotAvailableException.java: Tạo một ngoại lệ tùy chỉnh kế thừa từ Exception. Hàm khởi tạo nhận biển số xe và tạo thông báo theo định dạng Vehicle not available: [licensePlate].
  • Rentable.java: Tạo một interface định nghĩa các thao tác thuê xe. Khai báo các phương thức rent() trả về boolean, returnVehicle() trả về boolean và calculateCost(int days) trả về double.
  • Vehicle.java: Tạo một lớp cơ sở trừu tượng cho mọi loại xe. Thêm các trường riêng tư licensePlate (String), brand (String), dailyRate (double) và status (RentalStatus, được khởi tạo bằng AVAILABLE). Hàm khởi tạo nhận licensePlate, brand và dailyRate. Thêm các phương thức getter phù hợp và một phương thức setter cho status. Khai báo phương thức trừu tượng getVehicleType() trả về String. Triển khai phương thức getDetails() để trả về "[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]", trong đó dailyRate được định dạng với 2 chữ số thập phân.
  • Car.java: Tạo một lớp kế thừa Vehicle và triển khai Rentable. Thêm trường riêng tư seats (int). Hàm khởi tạo nhận licensePlate, brand, dailyRate và seats. Triển khai getVehicleType() để trả về "Car". Với rent(), nếu status là AVAILABLE, hãy đổi thành RENTED rồi trả về true; nếu không thì trả về false. Với returnVehicle(), nếu status là RENTED, hãy đổi thành AVAILABLE rồi trả về true; nếu không thì trả về false. Với calculateCost(int days), trả về dailyRate nhân với days.
  • Motorcycle.java: Tạo một lớp kế thừa Vehicle và triển khai Rentable. Thêm trường riêng tư engineCC (int). Hàm khởi tạo nhận licensePlate, brand, dailyRate và engineCC. Triển khai getVehicleType() để trả về "Motorcycle". Triển khai các phương thức của Rentable giống như trong Car, nhưng calculateCost() áp dụng mức giảm giá 10% (nhân với 0.9).
  • RentalAgency.java: Tạo một lớp quản lý đội xe bằng ArrayList. Thêm các phương thức:
    • addVehicle(Vehicle vehicle) - thêm một xe vào đội xe
    • findVehicle(String licensePlate) - trả về Vehicle hoặc null
    • rentVehicle(String licensePlate, int days) - tìm xe, thử cho thuê xe (ép kiểu sang Rentable) và trả về chi phí thuê. Ném VehicleNotAvailableException nếu không tìm thấy xe hoặc nếu rent() trả về false
    • returnVehicle(String licensePlate) - tìm và trả xe, trả về true nếu thành công
    • getAvailableVehicles() - trả về một ArrayList gồm các xe có trạng thái AVAILABLE
  • Main.java: Xây dựng dịch vụ cho thuê xe! Bạn sẽ nhận một chuỗi lệnh, trong đó các lệnh được phân tách bằng dấu phẩy:
    • ADD_CAR:licensePlate:brand:dailyRate:seats
    • ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC
    • RENT:licensePlate:days
    • RETURN:licensePlate
    • AVAILABLE

    Xử lý từng lệnh và in ra:

    • ADD_CAR/ADD_MOTORCYCLE: Added: [brand] ([vehicleType])
    • RENT: Rented [licensePlate] for [days] days - Total: $[cost] (chi phí có 2 chữ số thập phân), hoặc Error: [exception message]
    • RETURN: Returned: [licensePlate] hoặc Return failed: [licensePlate]
    • AVAILABLE: In ra Available vehicles:, sau đó in thông tin chi tiết của từng xe còn khả dụng trên các dòng riêng biệt

    Sau khi xử lý tất cả lệnh, in ra --- Fleet Summary ---, sau đó in thông tin chi tiết của từng xe.

Bạn sẽ nhận một đầu vào: chuỗi lệnh được phân tách bằng dấu phẩy.

Ví dụ, với đầu vào ADD_CAR:ABC-123:Toyota:50.00:5,ADD_MOTORCYCLE:XYZ-789:Honda:40.00:600,RENT:ABC-123:3,RENT:ABC-123:2,AVAILABLE,RETURN:ABC-123, đầu ra sẽ là:

Added: Toyota (Car)
Added: Honda (Motorcycle)
Rented ABC-123 for 3 days - Total: $150.00
Error: Vehicle not available: ABC-123
Available vehicles:
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent
Returned: ABC-123
--- Fleet Summary ---
ABC-123 Toyota (Car) - $50.00/day - ready to rent
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent

Thử thách này kết hợp kế thừa (hệ phân cấp Vehicle), interface (Rentable), enum (RentalStatus), ngoại lệ tùy chỉnh, tính đa hình (xử lý thống nhất các loại xe khác nhau) và tính hợp thành (RentalAgency quản lý các xe) thành một hệ thống dịch vụ cho thuê hoàn chỉnh!

Tự làm thử

import java.util.Scanner;
import java.util.ArrayList;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Tạo một instance của RentalAgency
        
        // TODO: Tách đầu vào theo dấu phẩy để lấy từng lệnh
        
        // TODO: Xử lý từng lệnh:
        // ADD_CAR:licensePlate:brand:dailyRate:seats -> in ra "Added: [brand] ([vehicleType])"
        // ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> in ra "Added: [brand] ([vehicleType])"
        // RENT:licensePlate:days -> in ra "Rented [licensePlate] for [days] days - Total: $[cost]" (2 chữ số thập phân)
        //                           hoặc "Error: [exception message]" nếu có ngoại lệ
        // RETURN:licensePlate -> in ra "Returned: [licensePlate]" hoặc "Return failed: [licensePlate]"
        // AVAILABLE -> in ra "Available vehicles:", sau đó là thông tin chi tiết của từng xe còn trống
        
        // TODO: Sau khi xử lý tất cả các lệnh, in ra "--- Fleet Summary ---"
        // sau đó là thông tin chi tiết của từng xe
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

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 Java online