📂
Interview Prep
LLD Questions
LLD Questions
  • LLD Introduction
  • Meeting Scheduler
  • Distributed Cache System
  • Rate limiter
  • Multi-Tier Elevator System
  • MyGate System
  • Uber Sytem LLD
  • Parking Lot System
  • Online book store
  • Library Management System
  • Movie Ticket Booking System
  • Hotel Management System
  • File Storage System
    • Solution 2
  • Chat Application
  • Social Media Platform
  • Notification System
  • Airline Reservation System
  • ATM System
  • E-commerce Website
  • Food Delivery System
  • Shopping Cart System
  • URL Shortener system
  • Chess Tournament System
  • Threading therory
  • OOP questions
Powered by GitBook
On this page
  • 🔹 Overview
  • 🔹 Design Patterns Used
  • 🔹 Complete Java Implementation
  • ✅ Final Features

Meeting Scheduler

🔹 Overview

A Meeting Scheduler system allows users to schedule, cancel, and manage meetings while ensuring no conflicts arise. The system also supports features like meeting reminders, notifications, and undo/redo operations.


🔹 Design Patterns Used

1️⃣ Singleton Pattern

  • Ensures only one instance of MeetingScheduler exists.

  • Centralized meeting management.

2️⃣ Factory Pattern

  • Encapsulates object creation for different meeting types (Virtual, In-Person).

  • Supports scalability when adding new meeting types.

3️⃣ Observer Pattern

  • Notifies users when a meeting is scheduled or canceled.

4️⃣ Strategy Pattern

  • Handles conflict resolution strategies dynamically.

5️⃣ Decorator Pattern

  • Adds meeting reminders dynamically without modifying existing meeting classes.

6️⃣ Command Pattern

  • Supports undo/redo functionality for meeting scheduling and cancellation.


🔹 Complete Java Implementation

import java.time.LocalDateTime;
import java.util.*;

// ==================== Singleton Pattern (MeetingScheduler) ====================
class MeetingScheduler {
    private static MeetingScheduler instance;
    private List<Meeting> meetings;
    private CommandHistory commandHistory;

    private MeetingScheduler() {
        meetings = new ArrayList<>();
        commandHistory = new CommandHistory();
    }

    public static synchronized MeetingScheduler getInstance() {
        if (instance == null) {
            instance = new MeetingScheduler();
        }
        return instance;
    }

    public boolean scheduleMeeting(Meeting meeting) {
        if (!isConflict(meeting)) {
            meetings.add(meeting);
            meeting.notifyObservers();
            commandHistory.executeCommand(new ScheduleMeetingCommand(this, meeting));
            return true;
        }
        return false;
    }

    public void cancelMeeting(Meeting meeting) {
        meetings.remove(meeting);
        System.out.println("Meeting '" + meeting.getTitle() + "' has been cancelled.");
        commandHistory.executeCommand(new CancelMeetingCommand(this, meeting));
    }

    public void undoLastAction() {
        commandHistory.undo();
    }

    private boolean isConflict(Meeting newMeeting) {
        for (Meeting meeting : meetings) {
            if (meeting.conflictsWith(newMeeting)) {
                return true;
            }
        }
        return false;
    }
}

// ==================== Observer Pattern (User) ====================
interface Observer {
    void update(Meeting meeting);
}

class User implements Observer {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public void update(Meeting meeting) {
        System.out.println("Notification: " + name + ", your meeting '" + meeting.getTitle() + "' is scheduled.");
    }

    public String getName() {
        return name;
    }
}

// ==================== Factory Pattern (Meeting Factory) ====================
abstract class Meeting {
    protected int id;
    protected String title;
    protected TimeSlot timeSlot;
    protected List<User> participants;
    private List<Observer> observers;

    public Meeting(int id, String title, TimeSlot timeSlot) {
        this.id = id;
        this.title = title;
        this.timeSlot = timeSlot;
        this.participants = new ArrayList<>();
        this.observers = new ArrayList<>();
    }

    public void addParticipant(User user) {
        participants.add(user);
        observers.add(user);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(this);
        }
    }

    public boolean conflictsWith(Meeting other) {
        return this.timeSlot.overlapsWith(other.timeSlot);
    }

    public String getTitle() {
        return title;
    }
}

// ==================== Concrete Meeting Types ====================
class InPersonMeeting extends Meeting {
    private String location;

    public InPersonMeeting(int id, String title, TimeSlot timeSlot, String location) {
        super(id, title, timeSlot);
        this.location = location;
    }
}

class VirtualMeeting extends Meeting {
    private String meetingLink;

    public VirtualMeeting(int id, String title, TimeSlot timeSlot, String meetingLink) {
        super(id, title, timeSlot);
        this.meetingLink = meetingLink;
    }
}

class MeetingFactory {
    public static Meeting createMeeting(String type, int id, String title, TimeSlot timeSlot, String extraDetail) {
        if (type.equalsIgnoreCase("inperson")) {
            return new InPersonMeeting(id, title, timeSlot, extraDetail);
        } else if (type.equalsIgnoreCase("virtual")) {
            return new VirtualMeeting(id, title, timeSlot, extraDetail);
        }
        throw new IllegalArgumentException("Invalid meeting type: " + type);
    }
}

// ==================== Decorator Pattern (Meeting Reminders) ====================
abstract class MeetingDecorator extends Meeting {
    protected Meeting decoratedMeeting;

    public MeetingDecorator(Meeting meeting) {
        super(meeting.id, meeting.title, meeting.timeSlot);
        this.decoratedMeeting = meeting;
    }

    public abstract void addFeature();
}

class MeetingWithReminder extends MeetingDecorator {
    private int reminderMinutesBefore;

    public MeetingWithReminder(Meeting meeting, int reminderMinutesBefore) {
        super(meeting);
        this.reminderMinutesBefore = reminderMinutesBefore;
    }

    @Override
    public void addFeature() {
        System.out.println("Reminder set: " + reminderMinutesBefore + " minutes before the meeting.");
    }
}

// ==================== Command Pattern (Undo/Redo) ====================
interface Command {
    void execute();
    void undo();
}

class ScheduleMeetingCommand implements Command {
    private MeetingScheduler scheduler;
    private Meeting meeting;

    public ScheduleMeetingCommand(MeetingScheduler scheduler, Meeting meeting) {
        this.scheduler = scheduler;
        this.meeting = meeting;
    }

    @Override
    public void execute() {
        scheduler.scheduleMeeting(meeting);
    }

    @Override
    public void undo() {
        scheduler.cancelMeeting(meeting);
    }
}

class CancelMeetingCommand implements Command {
    private MeetingScheduler scheduler;
    private Meeting meeting;

    public CancelMeetingCommand(MeetingScheduler scheduler, Meeting meeting) {
        this.scheduler = scheduler;
        this.meeting = meeting;
    }

    @Override
    public void execute() {
        scheduler.cancelMeeting(meeting);
    }

    @Override
    public void undo() {
        scheduler.scheduleMeeting(meeting);
    }
}

class CommandHistory {
    private Stack<Command> history = new Stack<>();

    public void executeCommand(Command command) {
        command.execute();
        history.push(command);
    }

    public void undo() {
        if (!history.isEmpty()) {
            Command lastCommand = history.pop();
            lastCommand.undo();
        }
    }
}

// ==================== TimeSlot ====================
class TimeSlot {
    private LocalDateTime startTime;
    private LocalDateTime endTime;

    public TimeSlot(LocalDateTime startTime, LocalDateTime endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public boolean overlapsWith(TimeSlot other) {
        return startTime.isBefore(other.endTime) && endTime.isAfter(other.startTime);
    }
}

// ==================== Main Class (Testing) ====================
public class Main {
    public static void main(String[] args) {
        MeetingScheduler scheduler = MeetingScheduler.getInstance();

        User alice = new User(1, "Alice");
        User bob = new User(2, "Bob");

        TimeSlot timeSlot1 = new TimeSlot(LocalDateTime.of(2025, 3, 10, 10, 0), LocalDateTime.of(2025, 3, 10, 11, 0));

        Meeting meeting1 = MeetingFactory.createMeeting("virtual", 101, "Project Kickoff", timeSlot1, "zoom.com/meeting1");
        meeting1.addParticipant(alice);
        meeting1.addParticipant(bob);

        Meeting meetingWithReminder = new MeetingWithReminder(meeting1, 15);
        ((MeetingWithReminder) meetingWithReminder).addFeature();

        if (scheduler.scheduleMeeting(meeting1)) {
            System.out.println("Meeting scheduled successfully.");
        }

        scheduler.undoLastAction();
    }
}

✅ Final Features

✅ Decorator Pattern → Add reminders dynamically. ✅ Command Pattern → Supports Undo/Redo actions. ✅ Factory Pattern → Encapsulated object creation.

Would you like further refinements? 🚀

PreviousLLD IntroductionNextDistributed Cache System

Last updated 2 months ago