Сервис аренды транспорта
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 87 из 87.
Для этого финального испытания вы создадите систему Сервиса аренды транспортных средств, которая объединяет все концепции ООП, освоенные вами на протяжении этого курса.
Ваша система должна моделировать парк транспортных средств различных типов. Рассмотрите базовый класс Vehicle с общими свойствами, такими как номерной знак, марка и ежедневная стоимость аренды. Подклассы, такие как Car, Motorcycle и Truck, могут расширять его специфическими атрибутами, такими как количество мест, объем двигателя или грузоподъемность.
Интерфейсы могут определять поведение аренды: интерфейс Rentable может объявлять такие методы, как rent(), returnVehicle() и calculateCost(int days). Различные типы транспортных средств могут реализовывать стратегии ценообразования по-разному, что делает это идеальным примером использования полиморфизма.
Подумайте о том, как класс RentalAgency управляет автопарком, используя композицию.
Пользовательские исключения, такие как VehicleNotAvailableException, могут обрабатывать пограничные случаи.
Вы можете применить паттерн «Фабрика» (Factory pattern) для создания транспортных средств или использовать перечисления (enums) для категорий транспортных средств и статуса аренды.
Это испытание проверяет вашу способность проектировать полноценную, хорошо структурированную систему ООП. Удачи!
Задание
ЛегкоДавайте создадим полноценный сервис по аренде автомобилей, который объединит все, что вы узнали об ООП! Вы создадите систему, которая управляет парком транспортных средств различных типов, обрабатывает аренду с надлежащей валидацией и использует паттерн «фабрика» для создания транспортных средств.
Вы организуете свой код в семи файлах:
RentalStatus.java: Создайте перечисление (enum), представляющее статус аренды транспортного средства. Включите значенияAVAILABLE,RENTEDиMAINTENANCE. Добавьте приватное полеdescription(String), конструктор и геттер.AVAILABLEдолжен иметь описание "ready to rent",RENTED— "currently in use", аMAINTENANCE— "under service".VehicleNotAvailableException.java: Создайте пользовательское исключение, которое расширяетException. Конструктор должен принимать номерной знак и создавать сообщение в форматеVehicle not available: [licensePlate].Rentable.java: Создайте интерфейс, определяющий операции аренды. Объявите методыrent(), возвращающий boolean,returnVehicle(), возвращающий boolean, иcalculateCost(int days), возвращающий double.Vehicle.java: Создайте абстрактный базовый класс для всех транспортных средств. Включите приватные поля дляlicensePlate(String),brand(String),dailyRate(double) иstatus(RentalStatus, инициализированный какAVAILABLE). Конструктор принимаетlicensePlate,brandиdailyRate. Включите соответствующие геттеры и сеттер дляstatus. Объявите абстрактный методgetVehicleType(), возвращающий String. Реализуйте методgetDetails(), который возвращает"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]", гдеdailyRateотформатирован до 2 знаков после запятой.Car.java: Создайте класс, расширяющийVehicleи реализующийRentable. Добавьте приватное полеseats(int). Конструктор принимаетlicensePlate,brand,dailyRateиseats. РеализуйтеgetVehicleType()так, чтобы он возвращал"Car". Дляrent(): если статусAVAILABLE, установите его вRENTEDи вернитеtrue; в противном случае вернитеfalse. ДляreturnVehicle(): если статусRENTED, установите его вAVAILABLEи вернитеtrue; в противном случае вернитеfalse. ДляcalculateCost(int days)вернитеdailyRate, умноженную наdays.Motorcycle.java: Создайте класс, расширяющийVehicleи реализующийRentable. Добавьте приватное полеengineCC(int). Конструктор принимаетlicensePlate,brand,dailyRateиengineCC. РеализуйтеgetVehicleType()так, чтобы он возвращал"Motorcycle". Реализуйте методыRentableтак же, как вCar, ноcalculateCost()должен применять скидку 10% (умножать на0.9).RentalAgency.java: Создайте класс, который управляет парком транспортных средств с помощьюArrayList. Включите методы:addVehicle(Vehicle vehicle)— добавляет транспортное средство в паркfindVehicle(String licensePlate)— возвращаетVehicleилиnullrentVehicle(String licensePlate, int days)— находит транспортное средство, пытается сдать его в аренду (приводя к типуRentable) и возвращает стоимость аренды. ВыбрасываетVehicleNotAvailableException, если транспортное средство не найдено или еслиrent()возвращаетfalsereturnVehicle(String licensePlate)— находит и возвращает транспортное средство, возвращаяtrueв случае успехаgetAvailableVehicles()— возвращаетArrayListтранспортных средств со статусомAVAILABLE
Main.java: Создайте свой сервис аренды! Вы получите строку команд, разделенных запятыми:ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
Обработайте каждую команду и выведите:
- ADD_CAR/ADD_MOTORCYCLE:
Added: [brand] ([vehicleType]) - RENT:
Rented [licensePlate] for [days] days - Total: $[cost](стоимость с 2 знаками после запятой) илиError: [exception message] - RETURN:
Returned: [licensePlate]илиReturn failed: [licensePlate] - AVAILABLE: Выведите
Available vehicles:, а затем детали каждого доступного транспортного средства на отдельных строках
После всех команд выведите
--- Fleet Summary ---, а затем детали каждого транспортного средства.
Вы получите один входной параметр: строку команд, разделенных запятыми.
Например, при входных данных 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 ваш вывод будет таким:
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Эта задача сочетает в себе наследование (иерархия Vehicle), интерфейсы (Rentable), перечисления (RentalStatus), пользовательские исключения, полиморфизм (единообразная работа с различными типами транспортных средств) и композицию (RentalAgency, управляющее транспортными средствами) в полноценную систему сервиса аренды!
Попробуйте сами
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: Создайте экземпляр RentalAgency
// TODO: Разделите входную строку по запятой, чтобы получить отдельные команды
// TODO: Обработайте каждую команду:
// ADD_CAR:licensePlate:brand:dailyRate:seats -> выведите "Added: [brand] ([vehicleType])"
// ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> выведите "Added: [brand] ([vehicleType])"
// RENT:licensePlate:days -> выведите "Rented [licensePlate] for [days] days - Total: $[cost]" (2 знака после запятой)
// или "Error: [exception message]", если возникло исключение
// RETURN:licensePlate -> выведите "Returned: [licensePlate]" или "Return failed: [licensePlate]"
// AVAILABLE -> выведите "Available vehicles:", а затем сведения о каждом доступном транспортном средстве
// TODO: После выполнения всех команд выведите "--- Fleet Summary ---"
// а затем сведения о каждом транспортном средстве
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy14Финальные испытания
Платформа онлайн-обученияБанковская системаРазработка игрового персонажаСервис аренды транспорта3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»