Requirements
Designing a parking lot system to manage vehicle parking across multiple floors. Include features for parking spot assignment based on vehicle size, spot availability checking, and fee calculation based on parking duration.
Define Core Objects
Floor/Level
Vehicle
ParkingSpot
ParkingTicket
ParkingLotManager
VehicleType
VehicleSize
Analyze Relationships
Establish Hierarchy
Design inheritance trees where applicable to promote code reuse and polymorphism. This step involves identifying common attributes and behaviors that can be abstracted into parent classes...
Design Patterns
Singleton Design Pattern: While creating the object of ParkingLot class
Strategy Design Pattern: Can be used to calculate parking fee based on multiple available conditions
Define Class Members (write code)
public class Car { ... } // Example
public enum VehicleType{
CAR,
MOTOR_CYCLE,
TRUCK
}
public enum SpotSize{
LARGE,
MEDIUM,
SMALL
}
public enum TicketStatus{
Active,
Paid
}
public abstract class Vehicle{
private String licensePlate;
private VehicleType vehicleType;
public Vehicle(String licensePlate,VehicleType vehicleType){
this.licensePlate=licensePlate;
this.vehicleType=vehicleType;
}
public VehicleType getType(){
return vehicleType;
}
}
public class Car extends Vehicle{
public Car(String licensePlate){
super(licensePlate,VehicleType.CAR);
}
}
public class MotorCycle extends Vehicle{
public MotorCycle(String licensePlate){
super(licensePlate,VehicleType.MOTOR_CYCLE);
}
}
public class Truck extends Vehicle{
public Truck(String licensePlate){
super(licensePlate,VehicleType.TRUCK);
}
}
public class ParingTicket{
private String ticketId;
private Timestamp issueTime;
private Timestamp closeTime;
private TicketStatus status;
private int paid;
public ParkingTicket(String ticketId, Timestamp issueTime){
this.ticketId=ticketId;
this.issueTime=issueTime;
}
public void setCloseTime(Timestamp time){
this.closeTime=time;
}
public void setStatus(TicketStatus status){
this.status=status;
}
public void setPaid(int amount){
this.paid=amount;
}
}
public class ParkingSpot{
private int spotNumber;
private SpotSize size;
private VehicleType vehicleType;
private Vehicle parkedVehicle;
private ParkingTicket ticket;
private static final int largeVehicleCost=20;
private static final int mediumVehicleCost=10;
private static final int smallVehicleCost=5;
public ParkingSpot(int spotNumber, SpotSize size,VehicleType vehicleType){
this.spotNumber=spotNumber;
this.size=size;
this.vehicleType=vehicleType;
}
public synchronized boolean isAvailable(){
return this.parkedVehicle==null;
}
public synchronized void parkVehicle(Vehicle vehicle){
if(isAvailable() && vehicle.getType()==vehicleType){
this.parkedVehicle=vehicle;
this.ticket=new ParkingTicket("1",Timestamp.from(Instant.now()),TicketStatus.Active);
}
public synchronized void unparkVehicle() {
TimeStamp start=ticket.getParkTime();
TimeStamp end=Timestamp.from(Instant.now());
long timeDifferenceMillis = Math.abs(timestamp1.getTime() - timestamp2.getTime());
int diff=(int) TimeUnit.MILLISECONDS.toHours(timeDifferenceMillis);
if(parkedVehicle .size==SpotSize.LARGE){
int cost=largeVehicleCost*diff;
ticket.setPaid(cost);
}
if(parkedVehicle .size==SpotSize.MEDIUM){
int cost=mediumVehicleCost*diff;
ticket.setPaid(cost);
}
if(parkedVehicle .size==SpotSize.SMALL){
int cost=smallVehicleCost*diff;
ticket.setPaid(cost);
}
parkedVehicle = null;
}
public VehicleType getVehicleType() {
return vehicleType;
}
public Vehicle getParkedVehicle() {
return parkedVehicle;
}
public int getSpotNumber() {
return spotNumber;
}
}
public class Level{
private int levelNumber;
private List
public Level(int levelNumber, int numSpots){
this.floor = floor;
parkingSpots = new ArrayList<>(numSpots);
// Assign spots in ration of 50:40:10 for bikes, cars and trucks
double spotsForBikes = 0.50;
double spotsForCars = 0.40;
int numBikes = (int) (numSpots * spotsForBikes);
int numCars = (int) (numSpots * spotsForCars);
for (int i = 1; i <= numBikes; i++) {
parkingSpots.add(new ParkingSpot(i,VehicleType.MOTORCYCLE,SpotSize.SMALL));
}
for (int i = numBikes + 1; i <= numBikes + numCars; i++) {
parkingSpots.add(new ParkingSpot(i,VehicleType.CAR,SpotSize.MEDIUM));
}
for (int i = numBikes + numCars + 1; i <= numSpots; i++) {
parkingSpots.add(new ParkingSpot(i,VehicleType.TRUCK,SpotSize.LARGE));
}
}
public synchronized boolean parkVehicle(Vehicle vehicle) {
for (ParkingSpot spot : parkingSpots) {
if (spot.isAvailable() && spot.getVehicleType() == vehicle.getType()) {
spot.parkVehicle(vehicle);
return true;
}
}
return false;
}
public synchronized boolean unparkVehicle(Vehicle vehicle) {
for (ParkingSpot spot : parkingSpots) {
if (!spot.isAvailable() && spot.getParkedVehicle().equals(vehicle)) {
spot.unparkVehicle();
return true;
}
}
return false;
}
}
public class ParkingLotManager {
private static ParkingLotManager instance;
private final List
private ParkingLot() {
levels = new ArrayList<>();
}
public static synchronized ParkingLot getInstance() {
if (instance == null) {
instance = new ParkingLot();
}
return instance;
}
public void addLevel(Level level) {
levels.add(level);
}
public boolean parkVehicle(Vehicle vehicle) {
for (Level level : levels) {
if (level.parkVehicle(vehicle)) {
System.out.println("Vehicle parked successfully.");
return true;
}
}
System.out.println("Could not park vehicle.");
return false;
}
public boolean unparkVehicle(Vehicle vehicle) {
for (Level level : levels) {
if (level.unparkVehicle(vehicle)) {
return true;
}
}
return false;
}
}
Adhere to SOLID Guidelines
Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...
Consider Scalability and Flexibility
Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...
Create/Explain your diagram(s)
Try creating a class, flow, state and/or sequence diagram using the diagramming tool. Mermaid flow diagrams can be used to represent system use cases. You can ask the interviewer bot to create a starter diagram if unfamiliar with the tool. Briefly explain your diagrams if necessary...
Future improvements
Critically examine your design for any flaws or areas for future improvement...