This project was built as part of a deep-dive into advanced software design principles. The goal was to implement a fully functional parking booking system that mimics real-world behavior—user logins, space availability, booking, pricing tiers, payments, sensor integration, admin controls, and more.
We designed and implemented the entire system from scratch in Java using proper software architecture (MVC) and six different design patterns including Singleton, Factory, Strategy, Observer, Composite, and State. It was a group project for our Software Design course and scored 95%.
Even though it started as a course assignment, we treated it like a real client deliverable. I uploaded the finished version to GitHub and tested it cleanly using Maven and Eclipse. The app runs fully as a GUI-based Java desktop program.
GUI-based Java parking system
Different user roles: students, faculty, staff, visitors
Pricing logic based on user type
Admin panel for managing parking lots and spaces
Integration of simulated “sensor” data
Booking, editing, cancellation, license plate handling
Payment system with multiple options
GUI built in Swing
CSV used for persistent data
Full object-oriented implementation with proper design patterns
Randoop used for automated test case generation
Maven-managed with mutation testing and code coverage using JaCoCo
This was one of the first big projects where architecture actually mattered. We couldn’t just slap code together—we had to plan everything. Learned a lot about proper system decomposition, using design patterns to reduce coupling, and the value of clean documentation and modular testing.
Also realized how powerful Maven is for build management, and how testing tools like Randoop and JaCoCo help identify weak spots in coverage. Still brushing up on Maven and mutation testing, but it made me appreciate the importance of CI-ready design even in student projects.
You can download the full source code and project files from the GitHub link below:
🔗 GitHub Repository – Smart Parking App 🔗
To run the project locally:
Make sure you have Java and Eclipse (or IntelliJ) installed.
Clone or download the repository as a ZIP and extract it.
Open Eclipse → File > Import > Existing Maven Project.
Select the project folder (contains the pom.xml file).
Build the project using Maven (it will auto-download dependencies).
Run the Main.java file to launch the GUI.
The app should open a GUI window where you can register users, book parking spaces, and access the admin features.
Fully working Java GUI app
Clean directory layout with src, test, and pom.xml
README file walking you through the build and run process
Tested using Randoop-generated suites and mutation analysis
Uses design patterns across the app (you can spot them in the class structure)
Proxy Pattern
The Proxy Pattern is demonstrated through the SuperManager class, which acts as a gatekeeper for restricted management actions such as account creation. It implements the same interface as ManagementTeam but adds access control logic to ensure only the SuperManager can perform sensitive operations. Internally, it can delegate routine tasks to the ManagementTeam. This pattern supports security and role-based restrictions while maintaining interface compatibility.
State Pattern
The State Pattern is implemented in the ParkingSpace class, which changes its behavior depending on its current internal state — such as Empty, Occupied, or UnderMaintenance. Rather than relying on conditionals scattered throughout the code, each state is encapsulated into its own class that implements a shared ParkingState interface. This pattern makes the system easier to maintain and extend, and aligns well with future goals like supporting dynamic state transitions or complex rule-based logic.
Factory Method
The Factory Method Pattern is used to abstract the instantiation of different user types via the UserFactory class. Depending on the input, the factory can return various User subclasses such as ClientUser or ManagementUser, allowing the system to decouple the creation logic from the GUI and business logic. This makes the system extensible and reduces the risk of errors associated with direct instantiation, especially as new user types are introduced in the future.
Facade Pattern
The Facade Pattern is implemented through the MainSystem class, which acts as a unified interface to a complex set of subsystems such as user management, bookings, payment processing, and parking space control. Instead of exposing these subsystems to the GUI classes directly, the MainSystem encapsulates all internal operations and provides simplified methods like loginUser(), createBooking(), and processPayment(). This approach reduces coupling between the UI and business logic and makes the system more maintainable and scalable.
Strategy Pattern
The Strategy Pattern is applied to support multiple interchangeable payment methods including credit card, debit card, and mobile payments. A common interface PaymentStrategy defines the structure for processing payments, and specific implementations like CreditCardPayment, DebitCardPayment, and MobilePayment define their respective behaviors. The PaymentProcessor class acts as the context and delegates the execution of the payment to the chosen strategy. This pattern allows us to easily introduce new payment types without modifying existing code, adhering to the Open-Closed Principle.
Singleton Pattern
The Singleton Pattern is used in core system classes such as MainSystem, MainGUI, and SuperManager to ensure that only one instance of each exists during the application's lifecycle. This pattern is particularly useful in our system for maintaining centralized control over system state and configuration, especially in cases where multiple instantiations would lead to inconsistent behavior or resource conflicts. The getInstance() method provides global access to the single instance, while the private constructor enforces controlled instantiation.