The Mediator Pattern is a behavioral design pattern that helps to reduce the complexity of communication between objects by centralizing it through a mediator object. This pattern is part of the "Gang of Four" design patterns and it can be useful in scenarios where the communication between objects is becoming too complex and unmanageable.
In this article, we will explore how to implement the Mediator Pattern in Golang and provide a realistic code example.
Example Scenario
Let's imagine a scenario where we have a chat room application where multiple users can join and send messages to each other. In this case, we can have a mediator object that will handle the communication between the users.
Implementing the Mediator Pattern in Golang
To implement the Mediator Pattern in Golang, we will start by defining an interface for our mediator object. This interface will define the methods that our mediator object will use to communicate with the different objects in our system.
type mediator interface {
addUser(user user)
sendMessage(sender user, message string)
}
In the code above, we define our mediator
interface with two methods: addUser
and sendMessage
. The addUser
method will be used to add new users to our system, while the sendMessage
method will be used to send messages between users.
Next, we will define our user
struct which will represent a user in our system.
type user struct {
id int
name string
}
In the code above, we define our user
struct with an id
and name
fields.
Now, we can create our chatRoomMediator
struct which will implement our mediator
interface.
type chatRoomMediator struct {
users []user
}
func (c *chatRoomMediator) addUser(user user) {
c.users = append(c.users, user)
}
func (c *chatRoomMediator) sendMessage(sender user, message string) {
for _, u := range c.users {
if u.id != sender.id {
fmt.Printf("%s sent message to %s: %s\\\\n", sender.name, u.name, message)
}
}
}
In the code above, we define our chatRoomMediator
struct with a users
field which is an array of user
structs. We also implement the addUser
and sendMessage
methods from our mediator
interface.
The addUser
method appends a new user to our users
array, while the sendMessage
method loops through all our users and sends the message to all users except the sender.
Finally, we can create our main function and test our Mediator Pattern implementation.
func main() {
mediator := &chatRoomMediator{}
user1 := user{id: 1, name: "user1"}
user2 := user{id: 2, name: "user2"}
user3 := user{id: 3, name: "user3"}
mediator.addUser(user1)
mediator.addUser(user2)
mediator.addUser(user3)
mediator.sendMessage(user1, "Hello, everyone!")
}
In the code above, we create our mediator
object and three user
objects. We add these users to our mediator
object using the addUser
method, and then we send a message from user1
to everyone using the sendMessage
method.
When we run our code, we should see the following output:
user1 sent message to user2: Hello, everyone!
user1 sent message to user3: Hello, everyone!
Comparison to Facade Pattern
The Facade Pattern is another design pattern that can be used to simplify the complexity of a system by providing a simplified interface to a larger body of code. While the Mediator Pattern focuses on simplifying communication between objects, the Facade Pattern focuses on simplifying the interface to a larger body of code.
In our chat room scenario, we could use the Facade Pattern to simplify the interface to the chat room system. For example, we could define a chatRoom
struct which would have methods like joinRoom
and sendMessage
. These methods would call the appropriate methods on our chatRoomMediator
object to handle the underlying complexity of the system.
The Mediator Pattern, on the other hand, focuses on simplifying communication between objects in a system. In our chat room scenario, the Mediator Pattern allows us to centralize communication between our users through a mediator object, which simplifies the communication between our users and reduces the overall complexity of the system.
Conclusion
In this article, we explored how to implement the Mediator Pattern in Golang. We created a realistic code example where we used the Mediator Pattern to manage the communication between users in a chat room application.
By using the Mediator Pattern, we were able to reduce the complexity of communication between our objects and centralize it through a mediator object.
We also compared the Mediator Pattern to the Facade Pattern and discussed how each pattern can be used to simplify the complexity of a system in different ways.
References
- “Design Patterns: Elements of Reusable Object-Oriented Software” by Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm