// Core Notification System LLD in Java - Robust & Optimized
import java.util.*;
import java.util.concurrent.*;
// Notification Service Interface
interface NotificationService {
void sendNotification(NotificationRequest request);
}
// Notification Channel Interface
interface NotificationChannel {
boolean send(NotificationMessage message);
}
// User Preference Service Interface
interface UserPreferenceService {
UserPreferences getPreferences(String userId);
}
// Data Classes
class NotificationRequest {
private String requestId;
private String notificationType;
private Map recipient;
private List channels;
private Map message;
private ScheduleDetails schedule;
private Map metadata;
// Constructors, Getters, Setters omitted for brevity
}
class NotificationEvent {
private String messageId;
private String timestamp;
private String notificationType;
private String channel;
private Map recipient;
private Map messageContent;
private Map metadata;
// Constructors, Getters, Setters omitted for brevity
}
class NotificationMessage {
private String messageId;
private String channel;
private Map recipient;
private String content;
// Constructors, Getters, Setters omitted for brevity
}
class UserPreferences {
private String userId;
private List preferredChannels;
private Map optOutStatus;
private Map rateLimits;
// Constructors, Getters, Setters omitted for brevity
}
class ScheduleDetails {
private Date scheduledTime;
// Constructors, Getters, Setters omitted for brevity
}
// Concrete Implementations
class NotificationServiceImpl implements NotificationService {
private final BlockingQueue notificationQueue = new LinkedBlockingQueue<>();
private final UserPreferenceService userPreferenceService = new UserPreferenceServiceImpl();
private final SchedulerService schedulerService = new SchedulerService();
private final RateLimiterService rateLimiter = new RateLimiterService();
private final NotificationChannelFactory channelFactory = new NotificationChannelFactory();
private final RetryMechanism retryMechanism = new RetryMechanism();
@Override
public void sendNotification(NotificationRequest request) {
UserPreferences preferences = userPreferenceService.getPreferences(request.getRecipient().get("userId"));
for (String channel : request.getChannels()) {
if (!preferences.getPreferredChannels().contains(channel) ||
preferences.getOptOutStatus().getOrDefault(channel, false) ||
!RateLimiterService.allow(preferences.getUserId(), channel)) {
continue;
}
NotificationEvent event = createEvent(request, channel);
if (request.getSchedule() != null) {
schedulerService.scheduleNotification(event);
} else {
notificationQueue.add(event);
processEvent(event);
}
}
}
private NotificationEvent createEvent(NotificationRequest request, String channel) {
// Event creation logic (populate fields)
return new NotificationEvent();
}
private void processEvent(NotificationEvent event) {
NotificationMessage message = new NotificationMessage(); // populate
NotificationChannel channel = channelFactory.getChannel(event.getChannel());
boolean success = channel.send(message);
if (!success) {
retryMechanism.retry(event);
}
}
}
// Channel Implementations
class EmailNotificationChannel implements NotificationChannel {
public boolean send(NotificationMessage message) {
System.out.println("Email sent to: " + message.getRecipient());
return true;
}
}
class SMSNotificationChannel implements NotificationChannel {
public boolean send(NotificationMessage message) {
System.out.println("SMS sent to: " + message.getRecipient());
return true;
}
}
class PushNotificationChannel implements NotificationChannel {
public boolean send(NotificationMessage message) {
System.out.println("Push notification sent to: " + message.getRecipient());
return true;
}
}
// Channel Factory for Dynamic Channel Retrieval
class NotificationChannelFactory {
private final Map channels = new HashMap<>();
public NotificationChannelFactory() {
channels.put("EMAIL", new EmailNotificationChannel());
channels.put("SMS", new SMSNotificationChannel());
channels.put("PUSH", new PushNotificationChannel());
}
public NotificationChannel getChannel(String channelType) {
return channels.get(channelType);
}
}
class UserPreferenceServiceImpl implements UserPreferenceService {
public UserPreferences getPreferences(String userId) {
// Fetch preferences from DB/cache (mocked here)
return new UserPreferences();
}
}
class SchedulerService {
public void scheduleNotification(NotificationEvent event) {
System.out.println("Notification scheduled: " + event);
}
}
class RateLimiterService {
public boolean allow(String userId, String channel) {
// Rate limiting logic (mocked true)
return true;
}
}
class RetryMechanism {
public void retry(NotificationEvent event) {
System.out.println("Retrying for event: " + event);
// Implement retry logic here
}
}
/*
UML Diagram
visit to visualize: https://www.planttext.com/
@startuml
interface NotificationService {
+ sendNotification(request: NotificationRequest)
}
interface NotificationChannel {
+ send(message: NotificationMessage): boolean
}
interface UserPreferenceService {
+ getPreferences(userId: String): UserPreferences
}
class NotificationRequest {
- requestId: String
- notificationType: String
- recipient: Map
- channels: List
- message: Map
- schedule: ScheduleDetails
- metadata: Map
}
class NotificationEvent {
- messageId: String
- timestamp: String
- notificationType: String
- channel: String
- recipient: Map
- messageContent: Map
- metadata: Map
}
class NotificationMessage {
- messageId: String
- channel: String
- recipient: Map
- content: String
}
class UserPreferences {
- userId: String
- preferredChannels: List
- optOutStatus: Map
- rateLimits: Map
}
class ScheduleDetails {
- scheduledTime: Date
}
class NotificationServiceImpl {
+ sendNotification(request: NotificationRequest)
- createEvent(request: NotificationRequest, channel: String): NotificationEvent
- processEvent(event: NotificationEvent)
}
class EmailNotificationChannel {
+ send(message: NotificationMessage): boolean
}
class SMSNotificationChannel {
+ send(message: NotificationMessage): boolean
}
class PushNotificationChannel {
+ send(message: NotificationMessage): boolean
}
class NotificationChannelFactory {
+ getChannel(channelType: String): NotificationChannel
}
class UserPreferenceServiceImpl {
+ getPreferences(userId: String): UserPreferences
}
class SchedulerService {
+ scheduleNotification(event: NotificationEvent)
}
class RateLimiterService {
+ allow(userId: String, channel: String): boolean
}
class RetryMechanism {
+ retry(event: NotificationEvent)
}
NotificationService <|-- NotificationServiceImpl
NotificationServiceImpl --> NotificationRequest
NotificationServiceImpl --> NotificationEvent
NotificationServiceImpl --> NotificationChannelFactory
NotificationServiceImpl --> UserPreferenceService
NotificationServiceImpl --> SchedulerService
NotificationServiceImpl --> RateLimiterService
NotificationServiceImpl --> RetryMechanism
NotificationChannel <|-- EmailNotificationChannel
NotificationChannel <|-- SMSNotificationChannel
NotificationChannel <|-- PushNotificationChannel
NotificationChannelFactory --> NotificationChannel
UserPreferenceService <|-- UserPreferenceServiceImpl
UserPreferenceServiceImpl --> UserPreferences
SchedulerService --> NotificationEvent
RateLimiterService --> NotificationEvent
RetryMechanism --> NotificationEvent
@enduml
*/