Menu
Coddy logo textTech

Сервис аренды транспорта

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 87 из 87.

Для этого финального испытания вы создадите систему Сервиса аренды транспортных средств, которая объединяет все концепции ООП, освоенные вами на протяжении этого курса.

Ваша система должна моделировать парк транспортных средств различных типов. Рассмотрите базовый класс Vehicle с общими свойствами, такими как номерной знак, марка и ежедневная стоимость аренды. Подклассы, такие как Car, Motorcycle и Truck, могут расширять его специфическими атрибутами, такими как количество мест, объем двигателя или грузоподъемность.

Интерфейсы могут определять поведение аренды: интерфейс Rentable может объявлять такие методы, как rent(), returnVehicle() и calculateCost(int days). Различные типы транспортных средств могут реализовывать стратегии ценообразования по-разному, что делает это идеальным примером использования полиморфизма.

Подумайте о том, как класс RentalAgency управляет автопарком, используя композицию.

Пользовательские исключения, такие как VehicleNotAvailableException, могут обрабатывать пограничные случаи.

Вы можете применить паттерн «Фабрика» (Factory pattern) для создания транспортных средств или использовать перечисления (enums) для категорий транспортных средств и статуса аренды.

Это испытание проверяет вашу способность проектировать полноценную, хорошо структурированную систему ООП. Удачи!

challenge icon

Задание

Легко

Давайте создадим полноценный сервис по аренде автомобилей, который объединит все, что вы узнали об ООП! Вы создадите систему, которая управляет парком транспортных средств различных типов, обрабатывает аренду с надлежащей валидацией и использует паттерн «фабрика» для создания транспортных средств.

Вы организуете свой код в семи файлах:

  • 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 или null
    • rentVehicle(String licensePlate, int days) — находит транспортное средство, пытается сдать его в аренду (приводя к типу Rentable) и возвращает стоимость аренды. Выбрасывает VehicleNotAvailableException, если транспортное средство не найдено или если rent() возвращает false
    • returnVehicle(String licensePlate) — находит и возвращает транспортное средство, возвращая true в случае успеха
    • getAvailableVehicles() — возвращает ArrayList транспортных средств со статусом AVAILABLE
  • Main.java: Создайте свой сервис аренды! Вы получите строку команд, разделенных запятыми:
    • ADD_CAR:licensePlate:brand:dailyRate:seats
    • ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC
    • RENT:licensePlate:days
    • RETURN:licensePlate
    • AVAILABLE

    Обработайте каждую команду и выведите:

    • 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 ---"
        // а затем сведения о каждом транспортном средстве
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование