OOD / Concurrency• Patterns: Strategy, Observer, State
Ride Sharing
Hard
Problem Summary
Design a Carpooling / Ride-Sharing Pool engine matching multiple riders traveling in the same directional corridor, validating detour constraints, and dynamically splitting fares.
Functional Scope
- Match multiple riders to a single shared vehicle along directional routes.
- Detour time threshold validation (e.g. maximum 10-minute detour for any passenger).
- Dynamic passenger fare sharing based on shared vs individual distance ratios.
- Vehicle capacity tracking (max 4 passengers seated simultaneously).
- Observer notifications alerting riders of intermediate pickup and dropoff stops.
Entity-Relationship (ER) Schema
PoolRide [1] --> [1] Driver PoolRide [1] --> [1..4] RiderBooking PoolRide [1] --> [*] WaypointStop PoolRide [1] --> [1] DetourStrategy
Design Approach
Apply the Strategy pattern for detour margin calculations and vehicle seat capacity synchronization to ensure carpool limits are strictly enforced.
Core Classes & Models
PoolRide (Driver, active passengers, route waypoints, vehicle capacity)RiderBooking (Rider, pickup, dropoff, fare)WaypointStop (Location, stopType: PICKUP, DROPOFF, riderReference)DetourStrategy (Calculates marginal travel time and route deviation)FareSplitStrategy (Proportionally shares costs among co-riders)
Code Blueprint
62 lines/**
* Low-Level Design: Ride Sharing Peer Service
* Design Patterns Applied:
* - Strategy Pattern: Route optimization and dynamic trip fare estimation
* - Observer Pattern: Real-time driver telemetry coordinates to rider
* - State Pattern: Ride lifecycle state machine (Requested, Matched, InTransit, Finished)
*/
import java.util.*;
enum RidePhase { REQUESTED, MATCHED, IN_TRANSIT, FINISHED }
// --- [DESIGN PATTERN: Strategy] Ride fare calculation ---
interface FareStrategy {
double calculateFare(double distanceKm, int seats);
}
class StandardCarpoolFareStrategy implements FareStrategy {
@Override
public double calculateFare(double distanceKm, int seats) {
return (4.0 + distanceKm * 1.5) / Math.max(1, seats);
}
}
// --- [DESIGN PATTERN: Observer] Telemetry tracking observer ---
interface DriverTelemetryObserver {
void onLocationUpdated(String driverId, double lat, double lng);
}
class RiderTrackingDisplay implements DriverTelemetryObserver {
@Override
public void onLocationUpdated(String driverId, double lat, double lng) {
System.out.printf("📍 [Live Map] Driver %s location: (%.4f, %.4f)%n", driverId, lat, lng);
}
}
class RideSharingCoordinator {
private final FareStrategy fareStrategy = new StandardCarpoolFareStrategy();
private final List<DriverTelemetryObserver> observers = new ArrayList<>();
public void addObserver(DriverTelemetryObserver o) { observers.add(o); }
public double quoteTrip(double distanceKm, int seats) {
return fareStrategy.calculateFare(distanceKm, seats);
}
public void updateDriverGps(String driverId, double lat, double lng) {
for (DriverTelemetryObserver o : observers) o.onLocationUpdated(driverId, lat, lng);
}
}
public class Main {
public static void main(String[] args) {
RideSharingCoordinator service = new RideSharingCoordinator();
service.addObserver(new RiderTrackingDisplay());
double fare = service.quoteTrip(15.0, 3);
System.out.printf("Split Carpool Fare per person: $%.2f%n", fare);
service.updateDriverGps("DRV-99", 37.7749, -122.4194);
}
}