Wypożyczalnia pojazdów
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 87 z 87.
W tym ostatnim wyzwaniu zbudujesz system wypożyczalni pojazdów, który łączy wszystkie poznane przez Ciebie koncepcje programowania obiektowego.
Twój system powinien modelować flotę pojazdów różnych typów. Rozważ klasę bazową Vehicle ze wspólnymi właściwościami, takimi jak numer rejestracyjny, marka i dzienna stawka za wynajem. Podklasy, takie jak Car, Motorcycle i Truck, mogą ją rozszerzać o specyficzne atrybuty, takie jak liczba miejsc, pojemność silnika lub ładowność.
Interfejsy mogą definiować zachowania związane z wynajmem: interfejs Rentable może deklarować metody takie jak rent(), returnVehicle() i calculateCost(int days). Różne typy pojazdów mogą implementować strategie cenowe na różne sposoby, co czyni to doskonałym zastosowaniem polimorfizmu.
Zastanów się, jak klasa RentalAgency zarządza flotą za pomocą kompozycji.
Niestandardowe wyjątki, takie jak VehicleNotAvailableException, mogą obsługiwać przypadki brzegowe.
Możesz zastosować wzorzec Factory do tworzenia pojazdów lub użyć typów wyliczeniowych dla kategorii pojazdów i statusu wypożyczenia.
To wyzwanie sprawdza Twoją umiejętność zaprojektowania kompletnego, dobrze ustrukturyzowanego systemu OOP. Powodzenia!
Wyzwanie
ŁatwyZbudujmy kompletny system wypożyczalni pojazdów, który łączy wszystko, czego nauczyłeś się o OOP! Utworzysz system zarządzający flotą różnych typów pojazdów, obsługujący wypożyczenia z odpowiednią walidacją i wykorzystujący wzorzec fabryki do tworzenia pojazdów.
Rozmieścisz swój kod w siedmiu plikach:
RentalStatus.java: Utwórz enum reprezentujący status wypożyczenia pojazdu. Uwzględnij wartościAVAILABLE,RENTEDiMAINTENANCE. Dodaj prywatne poledescription(String), konstruktor i getter. Status dostępności powinien mieć opis "ready to rent", status wypożyczenia — "currently in use", a status konserwacji — "under service".VehicleNotAvailableException.java: Utwórz własny wyjątek rozszerzającyException. Konstruktor powinien przyjmować numer rejestracyjny i tworzyć komunikat w formacieVehicle not available: [licensePlate].Rentable.java: Utwórz interfejs definiujący operacje wypożyczania. Zadeklaruj metodyrent()zwracającą wartość logiczną,returnVehicle()zwracającą wartość logiczną orazcalculateCost(int days)zwracającą wartość typu double.Vehicle.java: Utwórz abstrakcyjną klasę bazową dla wszystkich pojazdów. Uwzględnij prywatne pola:licensePlate(String),brand(String),dailyRate(double) istatus(RentalStatus, zainicjowany wartością AVAILABLE). Konstruktor przyjmuje licensePlate, brand i dailyRate. Dodaj odpowiednie gettery oraz setter dla statusu. Zadeklaruj metodę abstrakcyjnągetVehicleType()zwracającą wartość typu String. Zaimplementuj metodęgetDetails(), która zwraca"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]", przy czym dailyRate ma być sformatowane do 2 miejsc po przecinku.Car.java: Utwórz klasę rozszerzającą Vehicle i implementującą Rentable. Dodaj prywatne poleseats(int). Konstruktor przyjmuje licensePlate, brand, dailyRate i seats. ZaimplementujgetVehicleType(), aby zwracała"Car". W metodzierent(), jeśli status ma wartość AVAILABLE, ustaw go na RENTED i zwróć true; w przeciwnym razie zwróć false. W metodziereturnVehicle(), jeśli status ma wartość RENTED, ustaw go na AVAILABLE i zwróć true; w przeciwnym razie zwróć false. MetodacalculateCost(int days)powinna zwracać iloczyn dailyRate i days.Motorcycle.java: Utwórz klasę rozszerzającą Vehicle i implementującą Rentable. Dodaj prywatne poleengineCC(int). Konstruktor przyjmuje licensePlate, brand, dailyRate i engineCC. ZaimplementujgetVehicleType(), aby zwracała"Motorcycle". Zaimplementuj metody interfejsu Rentable tak samo jak w klasie Car, ale metodacalculateCost()powinna uwzględniać 10% rabatu (pomnożyć wynik przez 0.9).RentalAgency.java: Utwórz klasę zarządzającą flotą pojazdów za pomocą ArrayList. Dodaj metody:addVehicle(Vehicle vehicle)— dodaje pojazd do flotyfindVehicle(String licensePlate)— zwraca obiekt Vehicle albo nullrentVehicle(String licensePlate, int days)— wyszukuje pojazd, próbuje go wypożyczyć (rzutując typ na Rentable) i zwraca koszt wypożyczenia. ZgłaszaVehicleNotAvailableException, jeśli pojazd nie zostanie znaleziony lub jeśli rent() zwróci falsereturnVehicle(String licensePlate)— wyszukuje i zwraca pojazd, zwracając true w przypadku powodzeniagetAvailableVehicles()— zwraca ArrayList pojazdów ze statusem AVAILABLE
Main.java: Zbuduj system wypożyczalni! Otrzymasz rozdzielony przecinkami ciąg poleceń:ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
Przetwórz każde polecenie i wypisz:
- ADD_CAR/ADD_MOTORCYCLE:
Added: [brand] ([vehicleType]) - RENT:
Rented [licensePlate] for [days] days - Total: $[cost](koszt z dokładnością do 2 miejsc po przecinku) lubError: [exception message] - RETURN:
Returned: [licensePlate]lubReturn failed: [licensePlate] - AVAILABLE: Wypisz
Available vehicles:, a następnie szczegóły każdego dostępnego pojazdu, każdy w osobnym wierszu
Po przetworzeniu wszystkich poleceń wypisz
--- Fleet Summary ---, a następnie szczegóły każdego pojazdu.
Otrzymasz jedno wejście: rozdzielony przecinkami ciąg poleceń.
Na przykład dla wejścia 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 wynikiem będzie:
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 rentTo wyzwanie łączy dziedziczenie (hierarchię Vehicle), interfejsy (Rentable), enumy (RentalStatus), własne wyjątki, polimorfizm (jednolite traktowanie różnych typów pojazdów) i kompozycję (RentalAgency zarządzająca pojazdami) w kompletny system wypożyczalni!
Spróbuj swoich sił
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: Utwórz instancję RentalAgency
// TODO: Podziel dane wejściowe według przecinków, aby uzyskać poszczególne polecenia
// TODO: Przetwórz każde polecenie:
// ADD_CAR:licensePlate:brand:dailyRate:seats -> wypisz "Added: [brand] ([vehicleType])"
// ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> wypisz "Added: [brand] ([vehicleType])"
// RENT:licensePlate:days -> wypisz "Rented [licensePlate] for [days] days - Total: $[cost]" (2 miejsca po przecinku)
// lub "Error: [exception message]", jeśli zostanie zgłoszony wyjątek
// RETURN:licensePlate -> wypisz "Returned: [licensePlate]" lub "Return failed: [licensePlate]"
// AVAILABLE -> wypisz "Available vehicles:", a następnie szczegóły każdego dostępnego pojazdu
// TODO: Po przetworzeniu wszystkich poleceń wypisz "--- Fleet Summary ---"
// a następnie szczegóły każdego pojazdu
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy14Końcowe wyzwania
Platforma e-learningowaSystem bankowyTworzenie postaci do gryWypożyczalnia pojazdów3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online