Projektowanie parkingu przy użyciu zasad obiektowych polega na podziale systemu na klasy, atrybuty i metody, które odzwierciedlają byty ze świata rzeczywistego. Kluczowe komponenty, takie jak pojazdy i miejsca parkingowe, można modelować jako obiekty, a interakcje, takie jak parkowanie, można obsługiwać za pomocą metod. Takie podejście sprzyja ponownemu wykorzystaniu modułowości i łatwości konserwacji, dzięki czemu system jest łatwy w rozbudowie i zarządzaniu.
Jak zaprojektować parking w oparciu o zasady obiektowe?Założenia
Dla naszych celów w tej chwili przyjmiemy następujące założenia. Przyjęliśmy te konkretne założenia, aby dodać trochę złożoności do problemu bez dodawania zbyt wielu rzeczy.
- Parking jest wielopoziomowy. Każdy poziom ma wiele rzędów plam.
- Na parkingu można zaparkować motocykle, samochody osobowe i autobusy.
- Na parkingu znajdują się miejsca dla motocykli, miejsca kompaktowe i duże.
- Motocykl można zaparkować w dowolnym miejscu.
- Samochód można zaparkować albo w jednym kompaktowym miejscu, albo w jednym dużym miejscu.
- Autobus może zaparkować na pięciu dużych miejscach, następujących po sobie i w tym samym rzędzie. Nie może parkować w małych miejscach. W poniższej implementacji utworzyliśmy abstrakcyjną klasę Pojazd, z której dziedziczą Samochód Autobus i Motocykl.
Projektowanie obiektowe
Zaczynamy od stworzenia niezbędnych klas i upewnienia się, że każda klasa ma jasno określoną odpowiedzialność. Rozłóżmy projekt, koncentrując się na interakcji poszczególnych klas i metod.
1. Klasa pojazdu
TheVehicleklasa definiuje wspólne atrybuty i zachowania dla wszystkich typów pojazdów. Będzie służyć jako klasa bazowa dla bardziej specyficznych typów pojazdów, takich jakBus CarIMotorcycle.
public abstract class Vehicle { protected String licensePlate; protected int spotsNeeded; protected VehicleSize size; public Vehicle(String licensePlate VehicleSize size) { this.licensePlate = licensePlate; this.size = size; this.spotsNeeded = (size == VehicleSize.Large) ? 5 : 1; } public int getSpotsNeeded() { return spotsNeeded; } public VehicleSize getSize() { return size; } public String getLicensePlate() { return licensePlate; } public abstract boolean canFitInSpot(ParkingSpot spot); }
2. Klasy pojazdów betonowych
Autobus : Autobus wymaga 5 kolejnych dużych miejsc.
Javapublic class Bus extends Vehicle { public Bus(String licensePlate) { super(licensePlate VehicleSize.Large); } public boolean canFitInSpot(ParkingSpot spot) { return spot.getSpotSize() == VehicleSize.Large; } }
Samochód : Samochód można zaparkować na małych lub dużych miejscach.
Javapublic class Car extends Vehicle { public Car(String licensePlate) { super(licensePlate VehicleSize.Compact); } public boolean canFitInSpot(ParkingSpot spot) { return spot.getSpotSize() == VehicleSize.Compact || spot.getSpotSize() == VehicleSize.Large; } }
Motocykl : Motocykl można zaparkować w dowolnym miejscu
Javapublic class Motorcycle extends Vehicle { public Motorcycle(String licensePlate) { super(licensePlate VehicleSize.Motorcycle); } public boolean canFitInSpot(ParkingSpot spot) { return true; // Can park in any spot } }
3. Klasa ParkingSpot
TheParkingSpotklasa reprezentuje indywidualne miejsce parkingowe na parkingu. Odpowiada za zarządzanie jego dostępnością i weryfikację, czy konkretny pojazd zmieści się w danym miejscu.
- Mogliśmy to zaimplementować, tworząc klasy dla LargeSpot CompactSpot i MotorcycleSpot, które dziedziczą z ParkingSpot, ale to prawdopodobnie przesada.
- Plamy prawdopodobnie nie zachowują się inaczej niż ich rozmiar.
public class ParkingSpot { private Vehicle vehicle; private VehicleSize spotSize; private int row; private int spotNumber; private Level level; public ParkingSpot(Level level int row int spotNumber VehicleSize spotSize) { this.level = level; this.row = row; this.spotNumber = spotNumber; this.spotSize = spotSize; this.vehicle = null; } public boolean isAvailable() { return vehicle == null; } public boolean canFitVehicle(Vehicle vehicle) { return isAvailable() && vehicle.canFitInSpot(this); } public void parkVehicle(Vehicle vehicle) { if (canFitVehicle(vehicle)) { this.vehicle = vehicle; } } public void removeVehicle() { this.vehicle = null; } public VehicleSize getSpotSize() { return spotSize; } public int getRow() { return row; } public int getSpotNumber() { return spotNumber; } }
4. Klasa poziomu parkingu
TheLevelklasa reprezentuje poziom na parkingu. Zarządza zbiorem miejsc parkingowych i zapewnia metody parkowania i usuwania pojazdów.
public class Level { private int levelNumber; private ParkingSpot[] spots; public Level(int levelNumber int numSpots) { this.levelNumber = levelNumber; this.spots = new ParkingSpot[numSpots]; } public boolean parkVehicle(Vehicle vehicle) { for (ParkingSpot spot : spots) { if (spot.canFitVehicle(vehicle)) { spot.parkVehicle(vehicle); return true; } } return false; } public boolean removeVehicle(Vehicle vehicle) { for (ParkingSpot spot : spots) { if (spot.isOccupied() && spot.getVehicle().equals(vehicle)) { spot.removeVehicle(); return true; } } return false; } }
5. Klasa ParkingLot
TheParkingLotklasa reprezentuje cały parking. Zarządza wieloma poziomami i zapewnia metody parkowania i usuwania pojazdów z parkingu.
public class ParkingLot { private Level[] levels; public ParkingLot(int numLevels int numSpotsPerLevel) { levels = new Level[numLevels]; for (int i = 0; i < numLevels; i++) { levels[i] = new Level(i numSpotsPerLevel); } } public boolean parkVehicle(Vehicle vehicle) { for (Level level : levels) { if (level.parkVehicle(vehicle)) { return true; } } return false; // Parking failed (no spots available) } public boolean removeVehicle(Vehicle vehicle) { for (Level level : levels) { if (level.removeVehicle(vehicle)) { return true; } } return false; // Removal failed (vehicle not found) } }
6. Klasy Ticket i PaymentService
Aby zarządzać sprzedażą biletów i płatnościami, dodajemyTicketIPaymentServicezajęcia.
Klasa biletowa : Reprezentuje bilet wydawany podczas parkowania pojazdu. Rejestruje czas wjazdu i wyjazdu pojazdu z parkingu.
Javapublic class Ticket { private Vehicle vehicle; private Date issueTime; private Date exitTime; public Ticket(Vehicle vehicle) { this.vehicle = vehicle; this.issueTime = new Date(); } public void setExitTime(Date exitTime) { this.exitTime = exitTime; } public long getDuration() { return (exitTime.getTime() - issueTime.getTime()) / 1000; // Time in seconds } }
Klasa usługi płatności : Odpowiedzialny za obliczanie opłat parkingowych i przetwarzanie płatności.
Jawapubliczny klasa Usługa płatności { publiczny podwójnie oblicz opłatę(Bilet bilet) { długi czas trwania = bilet.getDuration(); // Prosty model opłat: `text`=