System requirements:
-
Multi-Floor Structure:
- The parking lot should have multiple floors.
- Each floor should have a unique identifier (e.g., Floor 1, Floor 2, etc.).
- The system should keep track of available spots on each floor.
-
Entry and Exit Points:
- Multiple entry and exit points should be supported.
- Each entry/exit point should have a unique identifier.
- Entry points should be able to issue parking tickets.
- Exit points should be able to process payments and allow vehicles to leave.
-
Parking Tickets:
- Tickets should be issued at entry points.
- Each ticket should have a unique identifier.
- Tickets should record entry time and date.
- Tickets should be linked to the specific vehicle.
-
Payment System:
- Support both automated exit panels and human parking attendants.
- Accept both cash and credit card payments.
- Allow for payment at info portals on each floor.
- Once paid, the ticket should be marked as "paid" to allow exit without additional payment.
-
Capacity Management:
- Track the total capacity of the parking lot.
- Prevent entry when the lot is full.
- Display "Full" message at entrance panels and on ground floor display board when at capacity.
-
Parking Spot Types:
- Support multiple types: Compact, Large, Handicapped, Motorcycle, Electric.
- Each floor should have a mix of different spot types.
- Track availability of each spot type separately.
-
Electric Vehicle Charging:
- Designate some spots for electric vehicles.
- These spots should have charging panels.
- Allow payment for both parking and charging at these spots.
-
Vehicle Types:
- Support different vehicle types: Car, Truck, Van, Motorcycle, etc.
- Match vehicle types to appropriate spot types.
-
Display Boards:
- Each floor should have a display board.
- Display boards should show free spots for each spot type on that floor.
-
Pricing Model:
- Implement a per-hour fee structure.
- First hour: $4
- Second and third hours: $3.5 each
- All subsequent hours: $2.5 each
- The system should be flexible to allow easy changes to this pricing model.
-
Admin Functionality:
- Allow adding, removing, and modifying parking floors.
- Allow adding, removing, and modifying parking spots.
- Allow adding and removing parking attendants.
- Allow modifying pricing structures.
-
Parking Attendant Functionality:
- Perform all customer actions on behalf of customers.
- Handle cash payments.
-
System Functionality:
- Display messages on info panels.
- Assign and remove vehicles from parking spots.
- Calculate parking duration and fees.
Object-Oriented Design for a Multi-Entrance and Exit Parking Lot System
Problem Analysis and Requirements Gathering
The parking lot system needs to handle various types of vehicles, different parking spot types, multiple floors, multiple payment methods, and dynamic pricing models. The system should also manage entry and exit points, display available parking spots, and support electric vehicle charging.
Key Components and Classes
To design this system, we need to identify the key entities and their relationships. Here's an overview of the main classes and their responsibilities:
- ParkingLot: Manages the overall parking lot, including floors, entry, and exit points.
- ParkingFloor: Represents a floor in the parking lot, containing multiple parking spots and a display board.
- ParkingSpot: Represents a single parking spot, which can be of various types (Compact, Large, Handicapped, Motorcycle, Electric).
- Vehicle: Represents a vehicle, which can be a car, truck, van, motorcycle, etc.
- Ticket: Represents a parking ticket issued to a vehicle upon entry.
- Payment: Manages payment transactions, which can be through cash, credit card, or other methods.
- DisplayBoard: Shows available parking spots on each floor.
- EntrancePanel: Issues parking tickets at the entry points.
- ExitPanel: Processes payments and exits at the exit points.
- Admin: Manages the parking lot configuration, including adding/removing floors, spots, and attendants.
- Customer: Represents a customer using the parking lot.
- ParkingAttendant: Represents an attendant who assists customers.
Class Implementations
1. ParkingLot Class
public class ParkingLot
{
private List<ParkingFloor> floors;
private List<EntrancePanel> entrances;
private List<ExitPanel> exits;
public ParkingLot()
{
floors = new List<ParkingFloor>();
entrances = new List<EntrancePanel>();
exits = new List<ExitPanel>();
}
public void AddFloor(ParkingFloor floor)
{
floors.Add(floor);
}
public void RemoveFloor(ParkingFloor floor)
{
floors.Remove(floor);
}
public void AddEntrance(EntrancePanel entrance)
{
entrances.Add(entrance);
}
public void AddExit(ExitPanel exit)
{
exits.Add(exit);
}
}
2. ParkingFloor Class
public class ParkingFloor
{
public int FloorNumber { get; private set; }
private List<ParkingSpot> spots;
public DisplayBoard DisplayBoard { get; private set; }
public ParkingFloor(int number)
{
FloorNumber = number;
spots = new List<ParkingSpot>();
DisplayBoard = new DisplayBoard();
}
public void AddParkingSpot(ParkingSpot spot)
{
spots.Add(spot);
DisplayBoard.Update(spots);
}
public void RemoveParkingSpot(ParkingSpot spot)
{
spots.Remove(spot);
DisplayBoard.Update(spots);
}
}
3. ParkingSpot Class
public class ParkingSpot
{
public int Id { get; private set; }
public SpotType Type { get; private set; }
public bool IsOccupied { get; private set; }
public ParkingSpot(int id, SpotType type)
{
Id = id;
Type = type;
IsOccupied = false;
}
public void ParkVehicle()
{
IsOccupied = true;
}
public void RemoveVehicle()
{
IsOccupied = false;
}
}
public enum SpotType
{
Compact,
Large,
Handicapped,
Motorcycle,
Electric
}
4. Vehicle Class
public class Vehicle
{
public string LicensePlate { get; private set; }
public VehicleType Type { get; private set; }
public Vehicle(string licensePlate, VehicleType type)
{
LicensePlate = licensePlate;
Type = type;
}
}
public enum VehicleType
{
Car,
Truck,
Van,
Motorcycle
}
5. Ticket Class
public class Ticket
{
public DateTime IssueTime { get; private set; }
public DateTime ExitTime { get; private set; }
public ParkingSpot Spot { get; private set; }
public Ticket(ParkingSpot spot)
{
IssueTime = DateTime.Now;
Spot = spot;
}
public void CloseTicket()
{
ExitTime = DateTime.Now;
}
}
6. Payment Class
public class Payment
{
public decimal Amount { get; private set; }
public PaymentMethod Method { get; private set; }
public Payment(decimal amount, PaymentMethod method)
{
Amount = amount;
Method = method;
}
}
public enum PaymentMethod
{
Cash,
CreditCard,
Coupon
}
7. DisplayBoard Class
public class DisplayBoard
{
public void Update(List<ParkingSpot> spots)
{
// Update display logic to show available spots
}
}
8. EntrancePanel Class
public class EntrancePanel
{
public Ticket IssueTicket(ParkingSpot spot)
{
return new Ticket(spot);
}
}
9. ExitPanel Class
public class ExitPanel
{
public void ProcessPayment(Ticket ticket, Payment payment)
{
ticket.CloseTicket();
// Process payment logic
}
}
10. Admin Class
public class Admin
{
private ParkingLot parkingLot;
public Admin(ParkingLot lot)
{
parkingLot = lot;
}
public void AddFloor(ParkingFloor floor)
{
parkingLot.AddFloor(floor);
}
public void RemoveFloor(ParkingFloor floor)
{
parkingLot.RemoveFloor(floor);
}
public void AddParkingSpot(ParkingFloor floor, ParkingSpot spot)
{
floor.AddParkingSpot(spot);
}
public void RemoveParkingSpot(ParkingFloor floor, ParkingSpot spot)
{
floor.RemoveParkingSpot(spot);
}
}
11. Customer Class
public class Customer
{
public Ticket GetTicket(EntrancePanel entrance, ParkingSpot spot)
{
return entrance.IssueTicket(spot);
}
public void PayFee(ExitPanel exit, Ticket ticket, Payment payment)
{
exit.ProcessPayment(ticket, payment);
}
}
12. ParkingAttendant Class
public class ParkingAttendant
{
public void AssistCustomer(Customer customer, EntrancePanel entrance, ParkingSpot spot)
{
Ticket ticket = customer.GetTicket(entrance, spot);
// Additional assistance logic
}
}
Reasoning Behind the Design
- Separation of Concerns: Each class is responsible for a single part of the system, making it easier to manage and extend.
- Encapsulation: Data and methods are encapsulated within classes, preventing unintended interference.
- Flexibility: The design can easily accommodate new requirements, such as additional payment methods or new types of parking spots.
- Maintainability: With clear class responsibilities, the system is easier to maintain and troubleshoot.
- Extensibility: The system can be extended with new features, such as different pricing models or additional vehicle types, without major changes to the existing codebase
.
This design covers the main aspects of a multi-floor, multi-entrance and exit parking lot system, ensuring it meets the outlined requirements while adhering to object-oriented design principles.
Areas for Improvement:
Interface Segregation: We should consider creating interfaces for some of our classes. For example, IPaymentProcessor could be implemented by both ExitPanel and a separate class for in-floor payment kiosks.
Pricing Model: The current design doesn't explicitly handle the complex pricing model described in the requirements. Consider adding a PricingStrategy class that can calculate fees based on parking duration.
Electric Vehicle Charging: While you've included an Electric spot type, the special functionality for EV charging isn't fully implemented. Consider adding an ElectricChargingSpot class that extends ParkingSpot.
Capacity Management: The design could benefit from a method to check if the parking lot is full and prevent new entries when at capacity.
Error Handling: Consider adding exception handling for scenarios like trying to park in an occupied spot or removing a non-existent floor.
Persistence: The current design doesn't address how data will be stored persistently. Consider adding a data access layer or using the repository pattern.
Parking Duration Calculation: Add a method in the Ticket class to calculate parking duration and cost.
Observer Pattern: Implement the observer pattern for the DisplayBoard to automatically update when ParkingSpot statuses change.
Factory Pattern: Consider using a factory pattern for creating different types of ParkingSpots and Vehicles.
Singleton Pattern: The ParkingLot class could potentially be a singleton, ensuring only one instance exists.
Revised Object-Oriented Design for the Parking Lot System
1. Interface Segregation
We will introduce interfaces for payment processing and other relevant components to adhere to the Interface Segregation Principle (ISP).
2. Pricing Model
We will add a PricingStrategy
class to handle different pricing models based on parking duration.
3. Electric Vehicle Charging
We will create an ElectricChargingSpot
class that extends ParkingSpot
to handle EV charging functionalities.
4. Capacity Management
We will add methods to check parking lot capacity and prevent new entries when the lot is full.
5. Error Handling
We will add exception handling for various scenarios such as parking in an occupied spot or removing a non-existent floor.
6. Persistence
We will outline a data access layer using the repository pattern to handle persistent storage.
7. Parking Duration Calculation
We will add methods in the Ticket
class to calculate parking duration and cost.
8. Observer Pattern
We will implement the observer pattern for the DisplayBoard
to automatically update when ParkingSpot
statuses change.
9. Factory Pattern
We will use the factory pattern for creating different types of ParkingSpots
and Vehicles
.
10. Singleton Pattern
We will make the ParkingLot
class a singleton to ensure only one instance exists.
Revised Class Implementations
1. Interfaces
public interface IPaymentProcessor
{
void ProcessPayment(Ticket ticket, Payment payment);
}
public interface IDisplay
{
void Update(List<ParkingSpot> spots);
}
2. PricingStrategy Class
public abstract class PricingStrategy
{
public abstract decimal CalculatePrice(TimeSpan duration);
}
public class HourlyPricingStrategy : PricingStrategy
{
public override decimal CalculatePrice(TimeSpan duration)
{
// Pricing logic here
// Example: $4 for the first hour, $3.5 for the second and third hours, $2.5 for subsequent hours
}
}
3. ElectricChargingSpot Class
public class ElectricChargingSpot : ParkingSpot
{
public ElectricChargingSpot(int id) : base(id, SpotType.Electric)
{
}
public void ChargeVehicle()
{
// Charging logic here
}
}
4. Capacity Management and Singleton Pattern
public class ParkingLot
{
private static ParkingLot instance;
private List<ParkingFloor> floors;
private List<EntrancePanel> entrances;
private List<ExitPanel> exits;
private int capacity;
private ParkingLot()
{
floors = new List<ParkingFloor>();
entrances = new List<EntrancePanel>();
exits = new List<ExitPanel>();
capacity = 0; // Initialize capacity
}
public static ParkingLot GetInstance()
{
if (instance == null)
{
instance = new ParkingLot();
}
return instance;
}
public void AddFloor(ParkingFloor floor)
{
floors.Add(floor);
capacity += floor.GetTotalSpots(); // Update capacity
}
public void RemoveFloor(ParkingFloor floor)
{
floors.Remove(floor);
capacity -= floor.GetTotalSpots(); // Update capacity
}
public bool IsFull()
{
return GetOccupiedSpots() >= capacity;
}
private int GetOccupiedSpots()
{
return floors.Sum(floor => floor.GetOccupiedSpots());
}
}
5. Error Handling
public class ParkingSpot
{
// Existing properties
public void ParkVehicle()
{
if (IsOccupied)
{
throw new InvalidOperationException("Parking spot is already occupied.");
}
IsOccupied = true;
}
public void RemoveVehicle()
{
if (!IsOccupied)
{
throw new InvalidOperationException("Parking spot is not occupied.");
}
IsOccupied = false;
}
}
6. Persistence with Repository Pattern
public interface IParkingRepository
{
void SaveTicket(Ticket ticket);
Ticket GetTicket(int id);
// Other CRUD operations
}
public class ParkingRepository : IParkingRepository
{
public void SaveTicket(Ticket ticket)
{
// Save ticket to database
}
public Ticket GetTicket(int id)
{
// Retrieve ticket from database
}
}
7. Parking Duration Calculation
public class Ticket
{
public DateTime IssueTime { get; private set; }
public DateTime ExitTime { get; private set; }
public ParkingSpot Spot { get; private set; }
public Ticket(ParkingSpot spot)
{
IssueTime = DateTime.Now;
Spot = spot;
}
public void CloseTicket()
{
ExitTime = DateTime.Now;
}
public TimeSpan GetParkingDuration()
{
return ExitTime - IssueTime;
}
public decimal CalculateCost(PricingStrategy pricingStrategy)
{
return pricingStrategy.CalculatePrice(GetParkingDuration());
}
}
8. Observer Pattern for DisplayBoard
public class DisplayBoard : IDisplay
{
public void Update(List<ParkingSpot> spots)
{
// Update display logic to show available spots
}
}
public class ParkingFloor
{
private List<ParkingSpot> spots;
private List<IDisplay> displays;
public ParkingFloor()
{
spots = new List<ParkingSpot>();
displays = new List<IDisplay>();
}
public void AddDisplay(IDisplay display)
{
displays.Add(display);
}
public void AddParkingSpot(ParkingSpot spot)
{
spots.Add(spot);
NotifyDisplays();
}
public void RemoveParkingSpot(ParkingSpot spot)
{
spots.Remove(spot);
NotifyDisplays();
}
private void NotifyDisplays()
{
foreach (var display in displays)
{
display.Update(spots);
}
}
}
9. Factory Pattern
public class ParkingSpotFactory
{
public static ParkingSpot CreateParkingSpot(int id, SpotType type)
{
switch (type)
{
case SpotType.Compact:
case SpotType.Large:
case SpotType.Handicapped:
case SpotType.Motorcycle:
return new ParkingSpot(id, type);
case SpotType.Electric:
return new ElectricChargingSpot(id);
default:
throw new ArgumentException("Invalid parking spot type.");
}
}
}
10. Singleton Pattern for ParkingLot Class
public class ParkingLot
{
private static readonly Lazy<ParkingLot> instance = new Lazy<ParkingLot>(() => new ParkingLot());
private List<ParkingFloor> floors;
private List<EntrancePanel> entrances;
private List<ExitPanel> exits;
private int capacity;
private ParkingLot()
{
floors = new List<ParkingFloor>();
entrances = new List<EntrancePanel>();
exits = new List<ExitPanel>();
capacity = 0;
}
public static ParkingLot Instance => instance.Value;
// Other methods...
}
Summary of Revisions
-
Interface Segregation: Introduced
IPaymentProcessor
andIDisplay
interfaces. -
Pricing Model: Added
PricingStrategy
andHourlyPricingStrategy
classes. -
Electric Vehicle Charging: Introduced
ElectricChargingSpot
class. -
Capacity Management: Added capacity management methods in
ParkingLot
. -
Error Handling: Included error handling in
ParkingSpot
. -
Persistence: Defined
IParkingRepository
andParkingRepository
. -
Parking Duration Calculation: Added duration calculation and cost calculation methods in
Ticket
. -
Observer Pattern: Implemented observer pattern for
DisplayBoard
. -
Factory Pattern: Used factory pattern for creating
ParkingSpot
andVehicle
objects. -
Singleton Pattern: Made
ParkingLot
a singleton.
These revisions enhance the design, making it more modular, maintainable, and scalable, while adhering to object-oriented design principles and best practices.
Top comments (0)