Design Pattern (21) Mediator Pattern: Smart Home System Component Coordination, Reducing Complex Coupling Relationships Between Objects

You can download the Design Pattern series code from this design_pattern repo.

Requirements

Our task is to design a chat room application. This system must handle real-time communication between multiple users. The following are three core requirements:

  • Message Transmission Mechanism: Users can send messages to other members through the chat room platform. The system needs to support one-to-many broadcast communication mechanisms, ensuring messages can be synchronously delivered to all relevant members.
  • User Independence: Each user doesn’t need to directly manage or know detailed information about other users. They only need to interact with the central platform, greatly simplifying individual user implementation complexity.
  • Dynamic Member Management: The system must support dynamic joining and leaving of users without affecting normal operation of other members. This flexibility is crucial for practical application scenarios.

From a design pattern perspective, this is a typical behavioral design pattern application scenario. We need to properly manage complex interaction relationships between multiple objects, avoiding maintenance problems caused by direct coupling.

Object-Oriented Analysis (OOA)

After understanding the requirements, we perform object-oriented analysis. In this chat room scenario, the core challenge we face is how to effectively manage complex interaction relationships between multiple users.

From a system architecture perspective, we need to address two key issues:

Problems with Direct Interaction Mode: If users communicate directly with each other, it forms complex mesh-like dependency relationships. Under this design, each user must know about the existence of all other users. As the number of users increases, this will lead to exponential growth in system complexity, significantly increasing maintenance costs.

Necessity of Central Coordination Mechanism: To solve the above problem, we need to introduce a centralized coordination role. This role acts as a mediator between users, responsible for unified management of all communication processes. Through this design, users only need to interact with the mediator without directly handling complex relationships with other users.

Recognizing Forces

In direct implementation without design patterns, we encounter the following four core challenges:

1. Mesh Coupling Problem (Mesh Coupling)

Users communicate directly with each other, forming complex mesh relationships. When adding a new user, all other users’ code needs to be updated to recognize this new member.

Similarly, when users leave, multiple reference relationships need to be cleaned up. This design makes system maintenance extremely difficult, where any small change can affect multiple components.

2. Difficulty in Feature Extension (Hard to Extend)

When advanced features need to be added (such as message filtering, private chat, group management, message history, etc.), multiple users’ logic must be modified simultaneously. This approach violates the Open-Closed Principle and significantly increases the risk of introducing bugs.

Each feature extension becomes a “pulling one hair affects the whole body” challenge, with low development efficiency and prone to errors.

3. Combinatorial Explosion Problem (Combinatorial Explosion)

As the number of users increases, the number of possible connections between users grows exponentially (n(n-1)/2). With 10 users, 45 connections need to be managed; with 100 users, 4950 connections are required.

This mathematical combinatorial explosion makes systems difficult to manage and maintain when scaling.

4. Responsibility Confusion (Responsibility Confusion)

Each user must bear communication management responsibilities, but this has no direct relationship with their main function (sending and receiving messages).

This responsibility confusion makes code difficult to understand and maintain, violating the Single Responsibility Principle design spirit.

Root Cause Analysis: The common root of these problems is the lack of mediation coordination mechanisms between objects, making complexity from direct interactions uncontrollably manageable.

Applying Mediator Pattern to Solve Problems

After object-oriented analysis and recognizing system challenges, we can apply the Mediator Pattern to effectively solve these problems.

Mediator Pattern is a behavioral design pattern. It effectively encapsulates complex interaction logic by defining interaction methods between objects. The main goal of this pattern is to promote loose coupling between objects while allowing developers to independently change interaction behaviors between objects.

Core Concepts of Mediator Pattern

The design essence of the mediator pattern lies in relationship restructuring: transforming originally complex many-to-many direct relationships into simple one-to-many star relationships.

In traditional design, each user needs to understand the existence and state of all other users. However, when we introduce a mediator, all users only need to interact with a single mediator. This transformation greatly simplifies system architecture and reduces maintenance complexity.

Mediator Pattern UML Structure

Roles and Responsibilities

Mediator Pattern systematically solves interaction complexity problems through the following four core roles:

1. Mediator (Mediator Interface)

Defines standard protocols for mediators, clearly specifying how to coordinate interactions between participants. In chat room scenarios, this interface covers core functions like message transmission and user management.

Through interface design, we ensure system extensibility and testability.

2. ConcreteMediator (Concrete Mediator)

Implements specific coordination logic, bearing the heavy responsibility of managing message exchange between all participants. It’s the only role that knows about the existence of all participants, responsible for coordinating all their interactions.

This role centralizes system control logic, making behavior more predictable and maintainable.

3. Colleague (Colleague Class)

Defines basic behavioral norms for participants and standard interaction methods with the mediator. This abstract layer ensures all participants follow unified protocols.

Importantly, all participants can only interact through the mediator, not allowing direct communication with other participants.

4. ConcreteColleague (Concrete Colleague Class)

Implements actual behaviors of specific participants. In our chat room example, these are different user entities.

Each concrete participant completely depends on the mediator to send and receive messages, ensuring system consistency and controllability.

Application to Chat Room Application

Object-Oriented Programming Implementation

Next, we’ll transform Mediator Pattern design theory into executable code. Through clear responsibility division, each component plays a specific role, collectively forming a complete and efficient mediator coordination system.

Let’s implement each core component step by step and observe how they work together.

Mediator - Mediator Interface

The mediator interface is the core contract of the entire system, defining standard protocols for coordinating interactions between participants. This interface ensures all concrete mediators follow consistent behavioral norms:

interface ChatMediator {
    fun sendMessage(message: String, user: User)
    fun addUser(user: User)
}

ConcreteMediator - Chat Room Mediator Implementation

The concrete mediator is the system’s control center, encapsulating all coordination logic. This class is responsible for maintaining the user list and handling all message transmission mechanisms:

class ChatRoomMediator : ChatMediator {
    private val users = mutableListOf<User>()

    override fun sendMessage(message: String, user: User) {
        users.filter { it != user }.forEach { it.receive(message) }
    }

    override fun addUser(user: User) {
        users.add(user)
    }
}

Colleague - User Abstract Class

The abstract user class establishes behavioral foundations for all participants. It not only defines basic send and receive functions but more importantly establishes standard interaction methods with the mediator:

abstract class User(protected val mediator: ChatMediator, val name: String) {
    abstract fun send(message: String)
    abstract fun receive(message: String)
}

ConcreteColleague - Concrete Chat Room User Implementation

The concrete user class implements actual chat functionality, demonstrating the core characteristic of the mediator pattern: all communication must go through the mediator. This design ensures system consistency:

class ChatUser(mediator: ChatMediator, name: String) : User(mediator, name) {
    override fun send(message: String) {
        println("$name sends message: $message")
        mediator.sendMessage(message, this)
    }

    override fun receive(message: String) {
        println("$name receives message: $message")
    }
}

Client - Client Usage Example

Client code demonstrates how to use the entire system. It clearly shows how to create chat rooms, add users, and how to manage user interactions through the mediator:

fun main() {
    val chatMediator = ChatRoomMediator()

    val user1 = ChatUser(chatMediator, "Alice")
    val user2 = ChatUser(chatMediator, "Bob")
    val user3 = ChatUser(chatMediator, "Charlie")

    chatMediator.addUser(user1)
    chatMediator.addUser(user2)
    chatMediator.addUser(user3)

    user1.send("Hello, everyone!")
    user2.send("Hi, Alice!")
}

Execution Results

Program execution output results are as follows:

Alice sends message: Hello, everyone!
Bob receives message: Hello, everyone!
Charlie receives message: Hello, everyone!
Bob sends message: Hi, Alice!
Alice receives message: Hi, Alice!
Charlie receives message: Hi, Alice!

Conclusion and Benefits

By applying the Mediator Pattern, we successfully solved all core problems originally faced by the system. Let’s examine specific improvement effects:

Main Improvement Effects

1. Breaking Mesh Coupling: We successfully transformed originally many-to-many complex relationships into one-to-many star relationships. Users no longer need to directly understand other users’ existence, and this architectural transformation significantly reduces system coupling.

From a maintenance perspective, this means modifying one user’s implementation won’t affect other users.

2. Centralized Control: All interaction logic is centrally managed in the mediator for unified management. This design makes system behavior easier to understand, predict, and control.

When debugging or monitoring system behavior, developers only need to focus on a single control point, greatly simplifying system analysis complexity.

3. Easy Feature Extension: When adding chat features (such as message filtering, private chat, group management, etc.), only mediator logic needs to be modified. This change completely doesn’t affect concrete user implementations.

This design follows the Open-Closed Principle, making systems open for extension and closed for modification.

4. Dynamic Participant Management: User joining and leaving becomes very simple, only requiring interaction with the mediator. Other users completely won’t perceive these changes, ensuring stable system operation.

This design is particularly suitable for application scenarios requiring dynamic participant adjustment.

Applicable Scenarios

Mediator Pattern is particularly suitable for the following four types of application scenarios:

  • Multi-user Interaction Systems: Such as chat rooms, multi-user collaboration platforms, online games, etc. These systems need to coordinate real-time interactions between multiple participants.
  • GUI Component Interaction: Managing complex interaction relationships between user interface components. For example, form validation, button state linkage, page component synchronization, etc.
  • Event Systems: Coordinating relationships between multiple event publishers and receivers. In this scenario, the mediator can serve as a central hub for event aggregation and distribution.
  • Workflow Systems: Managing interactions between various steps in complex business processes. The mediator can coordinate state transitions and data transmission between different stages.

Core Value Summary: The greatest value of this pattern lies in relationship transformation — transforming complex many-to-many interaction relationships into simple one-to-many mediation relationships. Through this architectural transformation, we not only greatly simplify system structural design but more importantly reduce long-term maintenance costs and complexity.




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • Claude Code 使用技巧與最佳實踐 - Tips and Best Practices
  • 🤖 AI Agent Series (Part 1): Understanding the Core Interaction Logic of LLM, RAG, and MCP
  • 💡 Managing Multiple GitHub Accounts on One Computer: The Simplest SSH Configuration Method
  • 🚀 How to Use Excalidraw AI to Quickly Generate Professional Diagrams and Boost Work Efficiency!
  • Complete macOS Development Environment Setup Guide: Mobile Development Toolchain Configuration Tutorial