Based on the requirements and use cases, identify the main objects of the system and analyze how they interact and relate to each other...
classDiagram
ParkingLot : +String name
ParkingLot : +String address
ParkingLot : +List<ParkingFloor> parkingFloors
ParkingLot : +List<Gate> gates
class ParkingLot{
+ParkingLotStatus status
+SpotAssignmentStratergy spotAssignmentStratergy
+FeeCalculationStratergy feeCaluclationStratergy
-Ticket parkVehicle(Vehicle vehicle,Gate entryGate)
-boolean isFull(VehicleType type)
}
class ParkingFloor{
+int id
+int floorNumber
+List<ParkingSpot> parkingSpots
-void markSpotOccupied(ParkingSpot parkingSpot)
-void markSpotAvailable(ParkingSpot parkingSpot)
}
class ParkingSpot{
-int id
-int spotNumber
-ParkingSpotType type
-ParkingSpotStatus status
-Vehicle parkedVehicle
-boolean canFitVehicle(Vehicle vehicle)
-void assignVehicle(Vehicle vehicle)
-void removeVehicle()
-boolean isAvailable()
}
class Vehicle{
+int id
+String vehicleNumber
+VehicleType type
+String ownerName
}
class Gate{
+int id
+int gateNumber
+Operator operator
+GateType type
}
class Operator{
+int id
+int empId
+String name
}
class Ticket{
+int id
+LocalDateTime entryTime
+Vehicle vehicle
+ParkingSpot spot
+Gate gate
+Operator issuedBy
+TicketStatus status
}
class Bill{
+int id
+LocalDateTime exitTime
+double amount
+Ticket ticket
+Gate exitGate
+Operator genratedBy
+List<Payment> payments
}
class Payment{
+int id
+double amount
+LocalDateTime time
+PaymentMode mode
+PaymentStatus status
+double refernceNumber
}
class SpotAssignmentStratergy{
<<interface>>
-Optional<ParkingSpot> assignSpot(List<ParkingFloor> floors,Vehicle vehicle)
}
class NearestSpotAssignmentStartergy{
-Optional<ParkingSpot> assignSpot(List<ParkingFloor> floors,Vehicle vehicle)
}
class FeeCalculationStartergy{
<<interface>>
-double calculateFee(Ticket ticket, LocalDateTime exitTime )
}
class HourlyFeeCalculationStrategy {
-double calculateFee(ParkingTicket ticket, LocalDateTime exitTime)
}
ParkingLot "1" o-- "*" ParkingFloor
ParkingFloor "1" o-- "*" ParkingSpot
ParkingLot "1" o--"*"Gate
Gate "1"--> "1" Operator
Ticket "1" --> "1" Vehicle
Ticket "1" --> "1"ParkingSpot
Ticket "1" --> "1"Gate
Bill "1" --> "1"Ticket
Bill "1"-->"*" Payment
ParkingLot --> SpotAssignmentStratergy
ParkingLot --> FeeCalculationStartergy
SpotAssignmentStratergy <|.. NearestSpotAssignmentStartergy
FeeCalculationStartergy <|.. HourlyFeeCalculationStrategy
The ParkingLot contains multiple ParkingFloor objects. It manages the overall parking facility and delegates the task of finding an available spot to the appropriate floor.
Each ParkingFloor contains multiple ParkingSpot objects. The floor finds and assigns an available spot to a vehicle based on its size.
A ParkingSpot is either occupied by a Vehicle or is vacant. When occupied, the spot stores a reference to the vehicle.
When a vehicle is parked, a Ticket is generated, recording the entry time, the assigned spot, and the vehicle. The ticket is used to calculate the parking fee.
Bill is generated using ticket and payment is made for the bill
For each class, define the attributes (data) it will hold and the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation. Write your code in the code editor below.
Explain design tradeoffs you considered. Check and explain whether your design adheres to SOLID principles. Explain how your design can handle changes in scale and whether it would be easy to extend with new functionalities. Identify areas for future improvement...
Factory pattern for creating vehicle objects according to the type of the vehicle
public class VehicleFactory{
public static Vehicle createVehicle(VehicleType type, String number){
switch(type.toLowerCase()){
case "car":
return new Car(number)
//rest of the vehicle types
}
}
}
SingleTon pattern for parkingLot object creation
public class ParkingLot{
private static ParkingLot instance;
private ParkingLot(){
}
public static synchronized ParkingLot getInstance(){
if(instance==null){
instance = new ParkingLot();
}
return instance;
}
}
Strategy pattern for fee calculation
Strategy pattern for spot assignment
Observer Pattern for notifying about spot availability
public interface ParkingObserver{
void update(String eventType,ParkingSpot spot)
}
public class ParkingSpot{
private List
public void addObserver(ParkingObserver observer) {
observers.add(observer);
}
public void removeObserver(ParkingObserver observer) {
observers.remove(observer);
}
public void notifyObservers(String eventType){
for(ParkingObserver observer : observers){
observer.update(eventType,this)
}
}
Solid
SRP
Each class have each responsibility for example parkinglot manages assigning vehicle a spot and Ticket class manages the entry details and duration of the user and Payment class handles the payment
OCP
New stratergies for fee calculation and spot assignment can be implemented without modifying
------------------------------------------------------------------------------------
Scalabilty
when spot and lot become much larger spot assignment will take time as it is checking all the spots so we can maintain indexed spot pools by spot type and floor
thread safety
we can use synchronised
renntrantLock
concurrent hashmap