> For the complete documentation index, see [llms.txt](https://mayanktyagi3111.gitbook.io/interview-prep/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mayanktyagi3111.gitbook.io/interview-prep/lld-questions/chat-application.md).

# Chat Application

#### **Key Features of the Chat Application**

1. **User**: Represents a user in the system with unique credentials (e.g., phone number, username).
2. **Message**: Represents a chat message that includes the sender, receiver, timestamp, and message content.
3. **ChatRoom**: A chat room represents a group chat where multiple users can send and receive messages.
4. **Real-time Communication**: Facilitates real-time message delivery through sockets (WebSocket or similar).
5. **User Authentication**: Ensures secure login and message exchange with proper authentication.
6. **Message Storage**: Stores sent and received messages in a database.
7. **Message Notifications**: Users are notified in real-time when they receive a new message.

#### **Design Patterns Used**

* **Singleton Pattern**: Used for managing the **ChatRoomManager** class that handles all chat rooms in the system.
* **Factory Pattern**: Used for creating instances of **Message** and **ChatRoom**.
* **Observer Pattern**: Used to notify users when a new message is received in real-time.
* **Command Pattern**: Used to send and receive messages in the system.

***

#### **Code Implementation**

**1. Singleton Pattern - `ChatRoomManager` Class**

The **Singleton Pattern** ensures that there is only one instance of `ChatRoomManager` managing all active chat rooms.

```java
import java.util.HashMap;
import java.util.Map;

// Singleton Pattern to manage active chat rooms
class ChatRoomManager {
    private static ChatRoomManager instance;
    private Map<String, ChatRoom> chatRooms;

    private ChatRoomManager() {
        chatRooms = new HashMap<>();
    }

    // Get the single instance of ChatRoomManager
    public static ChatRoomManager getInstance() {
        if (instance == null) {
            instance = new ChatRoomManager();
        }
        return instance;
    }

    // Create a chat room
    public ChatRoom createChatRoom(String roomName) {
        if (!chatRooms.containsKey(roomName)) {
            ChatRoom chatRoom = new ChatRoom(roomName);
            chatRooms.put(roomName, chatRoom);
            return chatRoom;
        }
        return null;  // Chat room already exists
    }

    // Get a chat room
    public ChatRoom getChatRoom(String roomName) {
        return chatRooms.get(roomName);
    }
}
```

**2. Factory Pattern - `MessageFactory` Class**

The **Factory Pattern** is used to create instances of messages.

```java
// Factory Pattern to create different types of messages
class MessageFactory {

    public static Message createMessage(String sender, String receiver, String content) {
        return new Message(sender, receiver, content);
    }
}
```

**3. Observer Pattern - `User` Class (Observer)**

The **Observer Pattern** is used to notify users when a new message is received in the chat room.

```java
import java.util.ArrayList;
import java.util.List;

// Observer Pattern: User receives notifications of new messages
class User implements Observer {
    private String username;
    private List<ChatRoom> chatRooms;

    public User(String username) {
        this.username = username;
        this.chatRooms = new ArrayList<>();
    }

    public String getUsername() {
        return username;
    }

    // Subscribe user to a chat room
    public void joinChatRoom(ChatRoom chatRoom) {
        chatRoom.addObserver(this);
        chatRooms.add(chatRoom);
    }

    // Receive notification about new messages
    @Override
    public void update(String message) {
        System.out.println(username + " received message: " + message);
    }

    // Unsubscribe from a chat room
    public void leaveChatRoom(ChatRoom chatRoom) {
        chatRoom.removeObserver(this);
        chatRooms.remove(chatRoom);
    }
}
```

**4. Command Pattern - `MessageCommand` Class**

The **Command Pattern** is used to encapsulate the message sending action.

```java
// Command Pattern to send a message
interface Command {
    void execute();
}

class MessageCommand implements Command {
    private Message message;
    private ChatRoom chatRoom;

    public MessageCommand(ChatRoom chatRoom, Message message) {
        this.chatRoom = chatRoom;
        this.message = message;
    }

    @Override
    public void execute() {
        chatRoom.sendMessage(message);  // Send message to the chat room
    }
}
```

**5. Chat Room Class**

The `ChatRoom` class contains the logic for managing users and sending messages. This uses the **Observer Pattern** to notify all users when a message is sent.

```java
import java.util.ArrayList;
import java.util.List;

// Chat Room class to manage users and messages
class ChatRoom {
    private String roomName;
    private List<Observer> observers;
    private List<Message> messageHistory;

    public ChatRoom(String roomName) {
        this.roomName = roomName;
        this.observers = new ArrayList<>();
        this.messageHistory = new ArrayList<>();
    }

    public String getRoomName() {
        return roomName;
    }

    // Add observer (user)
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    // Remove observer (user)
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    // Send message to all users in the chat room
    public void sendMessage(Message message) {
        messageHistory.add(message);
        for (Observer observer : observers) {
            observer.update(message.getContent());  // Notify all users
        }
    }

    // Retrieve message history
    public List<Message> getMessageHistory() {
        return messageHistory;
    }
}
```

**6. Message Class**

The `Message` class holds the details of a message including the sender, receiver, content, and timestamp.

```java
import java.time.LocalDateTime;

// Message class representing a chat message
class Message {
    private String sender;
    private String receiver;
    private String content;
    private LocalDateTime timestamp;

    public Message(String sender, String receiver, String content) {
        this.sender = sender;
        this.receiver = receiver;
        this.content = content;
        this.timestamp = LocalDateTime.now();
    }

    public String getSender() {
        return sender;
    }

    public String getReceiver() {
        return receiver;
    }

    public String getContent() {
        return content;
    }

    public LocalDateTime getTimestamp() {
        return timestamp;
    }
}
```

**7. Observer Interface**

The `Observer` interface ensures that the `User` class can receive updates from the `ChatRoom`.

```java
// Observer interface for receiving notifications
interface Observer {
    void update(String message);
}
```

**8. Authentication and Secure Communication**

For user authentication, we can use a secure system based on usernames and passwords. For simplicity, here’s an example of the `AuthService` class that could handle user authentication.

```java
import java.util.HashMap;
import java.util.Map;

class AuthService {
    private static final Map<String, String> userCredentials = new HashMap<>();  // Simple in-memory credential storage

    static {
        // Example credentials
        userCredentials.put("user1", "password1");
        userCredentials.put("user2", "password2");
    }

    // Authenticate user
    public static boolean authenticate(String username, String password) {
        String storedPassword = userCredentials.get(username);
        return storedPassword != null && storedPassword.equals(password);
    }
}
```

***

#### **Testing the System**

Below is a simple example to test the chat system with two users, a chat room, and message sending/receiving.

```java
public class Main {
    public static void main(String[] args) {
        // Create instances of users
        User user1 = new User("user1");
        User user2 = new User("user2");

        // Create a chat room
        ChatRoomManager chatRoomManager = ChatRoomManager.getInstance();
        ChatRoom chatRoom = chatRoomManager.createChatRoom("Friends");

        // Users join the chat room
        user1.joinChatRoom(chatRoom);
        user2.joinChatRoom(chatRoom);

        // Send a message
        Message message = MessageFactory.createMessage("user1", "user2", "Hello, how are you?");
        Command messageCommand = new MessageCommand(chatRoom, message);
        messageCommand.execute();  // Send message

        // Receive message (via observer pattern)
        user2.update("Hello, how are you?");
        
        // User2 sends a reply
        Message reply = MessageFactory.createMessage("user2", "user1", "I'm good, thanks!");
        messageCommand = new MessageCommand(chatRoom, reply);
        messageCommand.execute();  // Send reply
        
        // User1 receives the reply
        user1.update("I'm good, thanks!");
    }
}
```

***

#### **Summary of Design Patterns Used**

1. **Singleton Pattern**: Used in the `ChatRoomManager` class to ensure a single instance that manages all chat rooms in the system.
2. **Factory Pattern**: Used in `MessageFactory` to create new `Message` objects.
3. **Observer Pattern**: Used to notify all subscribed users (observers) in a chat room when a new message is sent.
4. **Command Pattern**: Used to encapsulate message sending actions, allowing easy message execution.

#### **Conclusion**

This low-level design of a **chat application** uses **design patterns** to create a modular, scalable system that supports real-time messaging, secure user authentication, and efficient chat room management. The use of patterns like **Singleton**, **Factory**, **Observer**, and **Command** ensures a clean and maintainable architecture while allowing easy extensions like adding multimedia messages or integrating with external chat services.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mayanktyagi3111.gitbook.io/interview-prep/lld-questions/chat-application.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
