1. Factory Pattern
The Factory Pattern can be used to create different types of events (e.g., one-time events, recurring events). This pattern helps in separating the instantiation logic from the client code.
Use Case: Creating different event types (standard, recurring, or specific event types like reminders or meetings).
import java.time.LocalDateTime;
// CalendarEvent Interface
interface CalendarEvent {
void createEvent();
}
// StandardCalendarEvent Class
class StandardCalendarEvent implements CalendarEvent {
private String title;
private String location;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String description;
public StandardCalendarEvent(String title, String location, LocalDateTime startTime, LocalDateTime endTime, String description) {
this.title = title;
this.location = location;
this.startTime = startTime;
this.endTime = endTime;
this.description = description;
}
@Override
public void createEvent() {
System.out.println("Standard Calendar Event created: " + this.title);
}
}
// RecurringCalendarEvent Class
class RecurringCalendarEvent implements CalendarEvent {
private String title;
private String location;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String description;
private String recurrencePattern;
public RecurringCalendarEvent(String title, String location, LocalDateTime startTime, LocalDateTime endTime, String description, String recurrencePattern) {
this.title = title;
this.location = location;
this.startTime = startTime;
this.endTime = endTime;
this.description = description;
this.recurrencePattern = recurrencePattern;
}
@Override
public void createEvent() {
System.out.println("Recurring Calendar Event created: " + this.title + " with pattern: " + this.recurrencePattern);
}
}
// CalendarEventFactory Class
public class CalendarEventFactory {
public static CalendarEvent getCalendarEvent(String type, String title, String location, LocalDateTime startTime, LocalDateTime endTime, String recurrencePattern) {
switch (type) {
case "Standard":
return new StandardCalendarEvent(title, location, startTime, endTime, "Standard Event");
case "Recurring":
return new RecurringCalendarEvent(title, location, startTime, endTime, "Recurring Event", recurrencePattern);
default:
throw new IllegalArgumentException("Unknown event type: " + type);
}
}
}
// Main Class to Demonstrate the Factory
public class Main {
public static void main(String[] args) {
// Create a standard calendar event
CalendarEvent standardEvent = CalendarEventFactory.getCalendarEvent(
"Standard",
"Team Meeting",
"Conference Room",
LocalDateTime.of(2024, 10, 15, 10, 0),
LocalDateTime.of(2024, 10, 15, 11, 0),
null
);
standardEvent.createEvent();
// Create a recurring calendar event
CalendarEvent recurringEvent = CalendarEventFactory.getCalendarEvent(
"Recurring",
"Weekly Sync",
"Online",
LocalDateTime.of(2024, 10, 16, 9, 0),
LocalDateTime.of(2024, 10, 16, 10, 0),
"Weekly"
);
recurringEvent.createEvent();
}
}
2. Observer Pattern
The Observer Pattern can be used when sharing events with multiple users. When an event is updated, all users who are "subscribed" to the event (observers) can be notified automatically.
Use Case: Notify participants of an event when changes (time, location, etc.) occur.
interface Observer {
void update(Event event);
}
class User implements Observer {
private String name;
public User(String name) {
this.name = name;
}
@Override
public void update(Event event) {
System.out.println("Notifying " + name + ": Event updated to " + event.getTitle());
}
}
class EventNotifier {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(Event event) {
for (Observer observer : observers) {
observer.update(event);
}
}
}
3. Singleton Pattern
The Singleton Pattern ensures that there is only one instance of certain classes. This is useful for managing global resources such as the calendar service or authentication module.
Use Case: Global management of calendar events or user sessions.
public class CalendarService {
private static CalendarService instance;
private CalendarService() {}
public static synchronized CalendarService getInstance() {
if (instance == null) {
instance = new CalendarService();
}
return instance;
}
// Other service-related methods
}
4. Strategy Pattern
The Strategy Pattern can be used to allow flexible management of finding available times for events based on different criteria like location, user availability, or time zone.
Use Case: Implement different strategies for scheduling based on location or availability.
interface SchedulingStrategy {
void schedule(Event event, List<User> users);
}
class LocationBasedScheduling implements SchedulingStrategy {
@Override
public void schedule(Event event, List<User> users) {
System.out.println("Scheduling event based on location...");
}
}
class AvailabilityBasedScheduling implements SchedulingStrategy {
@Override
public void schedule(Event event, List<User> users) {
System.out.println("Scheduling event based on user availability...");
}
}
5. Command Pattern
The Command Pattern can be used to handle user actions such as creating, updating, or deleting events. This also allows for undo/redo functionality.
Use Case: Managing event actions (create, update, delete) as commands that can be stored and possibly undone.
interface Command {
void execute();
void undo();
}
class CreateEventCommand implements Command {
private Event event;
public CreateEventCommand(Event event) {
this.event = event;
}
@Override
public void execute() {
event.createEvent();
}
@Override
public void undo() {
event.deleteEvent();
}
}
class CommandInvoker {
private List<Command> commandHistory = new ArrayList<>();
public void executeCommand(Command command) {
command.execute();
commandHistory.add(command);
}
public void undoLastCommand() {
if (!commandHistory.isEmpty()) {
Command command = commandHistory.remove(commandHistory.size() - 1);
command.undo();
}
}
}
6. Decorator Pattern
The Decorator Pattern can be used to add additional behavior or functionality to events, such as setting reminders or notifications.
Use Case: Extending event functionalities, like adding reminders or priority settings.
abstract class EventDecorator extends Event {
protected Event event;
public EventDecorator(Event event) {
super(event.getTitle(), event.getLocation(), event.getStartTime(), event.getEndTime(), event.getDescription());
this.event = event;
}
public abstract void addFeature();
}
class ReminderDecorator extends EventDecorator {
public ReminderDecorator(Event event) {
super(event);
}
@Override
public void addFeature() {
System.out.println("Adding reminder for event: " + event.getTitle());
}
}
7. Proxy Pattern
The Proxy Pattern can be used to control access to calendar events, especially when sharing with others (view or edit permissions).
Use Case: Handling access control when sharing events (e.g., allowing some users to view, others to edit).
interface Calendar {
void accessEvent(User user, Event event);
}
class RealCalendar implements Calendar {
@Override
public void accessEvent(User user, Event event) {
System.out.println(user.getName() + " accessed event: " + event.getTitle());
}
}
class CalendarProxy implements Calendar {
private RealCalendar realCalendar;
private boolean canEdit;
public CalendarProxy(boolean canEdit) {
this.realCalendar = new RealCalendar();
this.canEdit = canEdit;
}
@Override
public void accessEvent(User user, Event event) {
if (canEdit) {
System.out.println(user.getName() + " can edit event: " + event.getTitle());
} else {
System.out.println(user.getName() + " can only view event: " + event.getTitle());
}
}
}