Purpose of the pattern
Mediator is made for 1 thing only: Reducing Chaos between dependencies. Objects, instead of communicating with each other directly, will communicate through the Mediator.
What do we get from that?
- Less coupled code: classes don’t use multiple external dependencies.
- Reusability: classes don’t depend on each other and can be reused in other projects and places.
- Single Responsibility: communication responsibility is moved to the Mediator, making it easier to maintain and analyze.
- Open/Closed: introducing new Mediators doesn’t require changing any code in the existing codebase.
The biggest downside? Mediator might become a large monolith object with thousands of lines.
Implementation

The diagram above Mediator is an interface because we don’t want Colleague to depend on concrete classes but on abstraction. MediatorImpl is a concrete class that depends on all the Colleague concrete classes. We’re cleaning our codebase, but at the same time, we introduce very dirty MediatorImpl with multiple dependencies.
- Identify a group of tightly coupled classes that could be reused or are too dependent on each other, making your system too complex.
- Declare
Mediatorinterface. - Create a concrete
Mediatorclass that includes all the necessary dependencies. - Add
Mediatorinterface reference to the group of objects and remove previous dependencies. - Change the code so that it calls
Mediatorinstead of other classes.
Example
Your task is to make a Chat app with a group system. Each Chatter is in a group, can send and receive messages from other Chatter s. We’ll use Mediator to control messages sent to groups by Chatters . Here’s how we’ll structure our code:

Job Offers
Note that ChatMediator has a join method that needs to be called by the Chatters to receive messages.
Let’s start by adding Group :
enum class Group {
SPORT,
STUDENT;
}
For simplicity, we’ll only have 2 groups. Now, let’s define ChatMediator interface so we can create Chatters :
interface ChatMediator {
fun send(message: String, group: Group)
fun join(chatter: Chatter)
}
Now, let’s add Chatter along with SportsChatter and UniversityChatter :
interface Chatter {
fun send(message: String, group: Group)
fun receive(message: String)
val groups: Set<Group>
}
class SportsChatter(private val mediator: ChatMediator) : Chatter {
init {
mediator.join(this)
}
override fun send(message: String, group: Group) {
mediator.send(message, group)
}
override fun receive(message: String) {
print("Sports received $message")
}
override val groups: Set<Group>
get() = setOf(Group.SPORT)
}
// For simplicity this class is almost identical to SportsChatter
class UniversityChatter(private val mediator: ChatMediator) : Chatter {
init {
mediator.join(this)
}
override fun send(message: String, group: Group) {
mediator.send(message, group)
}
override fun receive(message: String) {
print("University received $message")
}
// Note that we have 2 Groups here!!
override val groups: Set<Group>
get() = setOf(Group.SPORT, Group.STUDENT)
}
Please note that UniversityChatter belongs to 2 groups Group.SPORT and Group.STUDENT . Finally, let’s implement GroupedChatMediator :
class GroupedChatMediator : ChatMediator {
private val chatters = mutableListOf<Chatter>()
override fun send(message: String, group: Group) {
chatters.forEach { chatter ->
if (chatter.groups.contains(group)) {
chatter.receive(message)
}
}
}
override fun join(chatter: Chatter) {
chatters.add(chatter)
}
}
Here’s how to use it:
fun main() {
val chatMediator: ChatMediator = GroupedChatMediator()
val sportsChatter: Chatter = SportsChatter(chatMediator)
val universityChatter: Chatter = UniversityChatter(chatMediator)
universityChatter.send("Student ", Group.STUDENT) // University
sportsChatter.send("Sport ", Group.SPORT) // University + Sports
// We can add in more Chatters
val sportsChatter2: Chatter = SportsChatter(chatMediator)
sportsChatter2.send("Sport ", Group.SPORT) // University + Sports + Sports
}
And that’s it Mediator is implemented! Well done.
Thanks for reading! Please clap if you learned something, and follow me for more!
Learn more about design patterns:
Based on the book:
“Wzorce projektowe : elementy oprogramowania obiektowego wielokrotnego użytku” — Erich Gamma Autor; Janusz Jabłonowski (Translator); Grady Booch (Introduction author); Richard Helm (Author); Ralph Johnson (Author); John M Vlissides (Author)
This article is previously published on proandroiddev.com


