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!
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,RENTEDvà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ạngVehicle 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ứcrent()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ượnggetVehicleType()trả về String. Triển khai phương thứcgetDetails()để 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 khaigetVehicleType()để trả về"Car". Vớirent(), 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ớireturnVehicle(), 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ớicalculateCost(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 khaigetVehicleType()để trả về"Motorcycle". Triển khai các phương thức của Rentable giống như trong Car, nhưngcalculateCost()á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 xefindVehicle(String licensePlate)- trả về Vehicle hoặc nullrentVehicle(String licensePlate, int days)- tìm xe, thử cho thuê xe (ép kiểu sang Rentable) và trả về chi phí thuê. NémVehicleNotAvailableExceptionnếu không tìm thấy xe hoặc nếu rent() trả về falsereturnVehicle(String licensePlate)- tìm và trả xe, trả về true nếu thành cônggetAvailableVehicles()- 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:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
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ặcError: [exception message] - RETURN:
Returned: [licensePlate]hoặcReturn 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 rentThử 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
}
}
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
1Kiến thức cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcTrường (thuộc tính)Phương thức khởi tạoNạp chồng phương thức khởi tạoÔn tập: Máy tính đơn giản4Kế thừa
Kế thừa cơ bản (extends)Từ khóa superGhi đè phương thức (@Override)Chuỗi gọi hàm khởi tạoLớp ObjectKế thừa đơn và đa cấpVì sao không hỗ trợ kế thừa nhiều lớpÔn tập: Phân cấp lớp Employee7Phương thức đặc biệt và lớp Object
Phương thức toString()equals() và hashCode()Phương thức clone()compareTo() và ComparableGiao diện ComparatorÔn tập: sắp xếp tùy chỉnh2Bộ điều chỉnh quyền truy cập và đóng gói
Tổng quan về các mức truy cậpPhương thức getter và setterẨn thông tinTừ khóa finalÔn tập: Trình quản lý tài khoản ngân hàng5Tính đa hình
Kiến thức cơ bản về nạp chồng phương thứcGhi đè phương thức (thời gian chạy)Chuyển kiểu lên và chuyển kiểu xuốngToán tử instanceofLớp và phương thức trừu tượngÔn tập: máy tính hình học8Khái niệm OOP nâng cao
Kết hợp và kế thừaKết tập và hợp thànhLớp bên trong, lớp lồng nhau và lớp ẩn danhKiểu enum và phương thức enumBản ghi (Java 16+)Lớp sealed (Java 17+)11Mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếMẫu SingletonMẫu FactoryMẫu BuilderMẫu ObserverMẫu Strategy14Thử thách cuối cùng
Nền tảng học trực tuyếnHệ thống ngân hàngPhát triển nhân vật trò chơiDịch vụ cho thuê phương tiện3Thuộc tính lớp và thành viên tĩnh
Biến của instance và biến tĩnhPhương thức tĩnhKhối tĩnhHằng số (static final)Ôn tập: bộ đếm và tiện ích6Giao diện và lớp trừu tượng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnPhương thức mặc định và tĩnh trong giao diệnLớp trừu tượng và giao diệnGiao diện hàmÔn tập: hệ thống thanh toán9Kiểu tổng quát
Giới thiệu về kiểu tổng quátLớp tổng quátPhương thức tổng quátTham số kiểu có giới hạnKý tự đại diện (?, extends, super)Ôn tập: vùng chứa tổng quát12Mẫu thiết kế, phần 2
Mẫu CommandMẫu AdapterMẫu DecoratorMẫu Template MethodMẫu StateMẫu CompositeMẫu IteratorTự luyện tập: Trình biên dịch Java online