Code · LLD machine coding · Personal project
Car Rental System
Search cars by make, model and dates; reserve, cancel, and pay. Overlapping reservations are rejected, and reservations are thread-safe.
CarRentalSystem.java 74 lines
package carrentalsystem;
import carrentalsystem.entities.Car;
import carrentalsystem.entities.Customer;
import carrentalsystem.entities.Reservation;
import carrentalsystem.payment.CreditCardPaymentProcessor;
import carrentalsystem.payment.PaymentProcessor;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class CarRentalSystem {
private static CarRentalSystem instance = new CarRentalSystem();
private final ConcurrentHashMap<String , Car> cars;
private final ConcurrentHashMap<String, Reservation> reservations;
private final PaymentProcessor paymentProcessor;
private CarRentalSystem() {
cars = new ConcurrentHashMap<>();
reservations = new ConcurrentHashMap<>();
paymentProcessor = new CreditCardPaymentProcessor();
}
public static CarRentalSystem getInstance() {
return instance;
}
public void addCar(Car car) {
cars.put(car.getLicencePlate(), car);
}
public void removeCar(Car car) {
cars.remove(car.getLicencePlate());
}
public List<Car> searchCars(String make, String model, LocalDate startDate, LocalDate endDate) {
List<Car> availableCars = new ArrayList<>();
for (Car car : cars.values()) {
if (car.getName().equalsIgnoreCase(make) && car.getModel().equalsIgnoreCase(model) && car.isAvailable()) {
if (isCarAvailable(car, startDate, endDate)) {
availableCars.add(car);
}
}
}
return availableCars;
}
private boolean isCarAvailable(Car car, LocalDate startDate, LocalDate endDate) {
for (Reservation reservation : reservations.values()) {
if (reservation.getCar().equals(car)) {
if (startDate.isBefore(reservation.getEndDate()) && endDate.isAfter(reservation.getStartDate())) {
return false;
}
}
}
return true;
}
public synchronized Reservation makeReservation(Customer customer, Car car, LocalDate startDate, LocalDate endDate) {
if (isCarAvailable(car, startDate, endDate)) {
String reservationId = generateReservationId();
Reservation reservation = new Reservation(reservationId, customer, car, startDate, endDate);
reservations.put(reservationId, reservation);
car.setAvailable(false);
return reservation;
}
return null;
}
public synchronized void cancelReservation(String reservationId) {
Reservation reservation = reservations.remove(reservationId);
if (reservation != null) {
reservation.getCar().setAvailable(true);
}
}
public boolean processPayment(Reservation reservation) {
return paymentProcessor.processPayment(reservation.getTotalPrice());
}
private String generateReservationId() {
return "RES" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
}
} entities/Car.java 38 lines
package carrentalsystem.entities;
public class Car {
private final String name;
private final String model;
private final int year;
private final String licencePlate;
private final double pricePerDay;
private boolean available;
public Car(String name, String model, int year, String licencePlate, double pricePerDay) {
this.available = true;
this.name = name;
this.year = year;
this.licencePlate = licencePlate;
this.pricePerDay = pricePerDay;
this.model = model;
}
public String getName() {
return name;
}
public String getModel() {
return model;
}
public int getYear() {
return year;
}
public String getLicencePlate() {
return licencePlate;
}
public double getPricePerDay() {
return pricePerDay;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
} entities/Customer.java 11 lines
package carrentalsystem.entities;
public class Customer {
private final String name;
private final String driversLicenseNumber;
private final String contactInfo;
public Customer(String name, String contactInfo, String driversLicenseNumber) {
this.name = name;
this.contactInfo = contactInfo;
this.driversLicenseNumber = driversLicenseNumber;
}
} entities/Reservation.java 39 lines
package carrentalsystem.entities;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
public class Reservation {
private final String reservationId;
private final Customer customer;
private final Car car;
private final LocalDate startDate;
private final LocalDate endDate;
private final double totalPrice;
public Reservation(String reservationId, Customer customer, Car car, LocalDate startDate, LocalDate endDate) {
this.reservationId = reservationId;
this.customer = customer;
this.car = car;
this.startDate = startDate;
this.endDate = endDate;
this.totalPrice = calculateTotalPrice();
}
private double calculateTotalPrice() {
long daysRented = ChronoUnit.DAYS.between(startDate, endDate) + 1;
return car.getPricePerDay() * daysRented;
}
public LocalDate getStartDate() {
return startDate;
}
public LocalDate getEndDate() {
return endDate;
}
public Car getCar() {
return car;
}
public double getTotalPrice() {
return totalPrice;
}
public String getReservationId() {
return reservationId;
}
} payment/CreditCardPaymentProcessor.java 7 lines
package carrentalsystem.payment;
public class CreditCardPaymentProcessor implements PaymentProcessor{
@Override
public boolean processPayment(double amount) {
return true;
}
} payment/PaymentProcessor.java 4 lines
package carrentalsystem.payment;
public interface PaymentProcessor {
boolean processPayment(double amount);
} type/CarStatus.java 4 lines
package carrentalsystem.type;
public enum CarStatus {
AVAILABLE, BOOKED, MAINTENANCE
} type/CarType.java 4 lines
package carrentalsystem.type;
public enum CarType {
SUV, SEDAN, HATCHBACK
} CarRentalSystemDemo.java 38 lines
package carrentalsystem;
import carrentalsystem.entities.Car;
import carrentalsystem.entities.Customer;
import carrentalsystem.entities.Reservation;
import java.time.LocalDate;
import java.util.List;
public class CarRentalSystemDemo {
public static void main(String[] args) {
CarRentalSystem carRentalSystem = CarRentalSystem.getInstance();
// Add cars to the rental system
carRentalSystem.addCar(new Car("Toyota", "Camry", 2022, "ABC123", 50.0));
carRentalSystem.addCar(new Car("Honda", "Civic", 2021, "XYZ789", 45.0));
carRentalSystem.addCar(new Car("Ford", "Mustang", 2023, "DEF456", 80.0));
// Create customers
Customer customer1 = new Customer("John Doe", "john@example.com", "DL1234");
// Make reservations
LocalDate startDate = LocalDate.now();
LocalDate endDate = startDate.plusDays(3);
List<Car> availableCars = carRentalSystem.searchCars("Toyota", "Camry", startDate, endDate);
if (!availableCars.isEmpty()) {
Car selectedCar = availableCars.get(0);
Reservation reservation = carRentalSystem.makeReservation(customer1, selectedCar, startDate, endDate);
if (reservation != null) {
boolean paymentSuccess = carRentalSystem.processPayment(reservation);
if (paymentSuccess) {
System.out.println("Reservation successful. Reservation ID: " + reservation.getReservationId());
} else {
System.out.println("Payment failed. Reservation canceled.");
carRentalSystem.cancelReservation(reservation.getReservationId());
}
} else {
System.out.println("Selected car is not available for the given dates.");
}
} else {
System.out.println("No available cars found for the given criteria.");
}
}
}