Go Patterns

Mediator Pattern in Go

Behavioral Design Pattern in Go

Go Mediator Design Pattern

Concept

Sometimes we have a bunch of objects that need to interact with each other. A number of objects can be large and their interactions can have complex logic.

Mediator pattern helps to organize such cases.

mediator

Let’s look for an example!

A chat

For example, we have a bunch of Users and they want to interact with each other.

So we introduce a Chat object that keeps this logic and organizes communication.

gophers chat

User type

Firstly, we will introduce a User type. It will have a Name and store Messages.

type User struct {
	Name     string
	Messages []string
}

Chat type

Then we need a Chat type. It will have a method to Add a User and keep information about Users in the Chat. This is our Mediator.

type Chat struct {
	Users map[string]*User
}

func NewChat() *Chat {
	return &Chat{make(map[string]*User)}
}

func (c *Chat) Add(user User) {
	c.Users[user.Name] = &user
}

Interaction logic

Now, let’s extend our Chat with interaction logic.

type Chat struct {
	Users map[string]*User
}

func (c *Chat) Say(to User, msg string) error {
	user, ok := c.Users[to.Name]
	if !ok {
		return fmt.Errorf("%s not in the chat\n", to.Name)
	}
	user.Messages = append(user.Messages, msg)
	return nil
}

func (c *Chat) SayAll(msg string) {
	for _, user := range c.Users {
		user.Messages = append(user.Messages, msg)
	}
}

Usage Example

Now, we gather all pieces together to see how it works.

func main() {
	// Create users
	John := User{Name: "John"}
	Bob := User{Name: "Bob"}
	Alice := User{Name: "Alice"}
	// Create chat
	chat := NewChat()
	// Add users to the chat
	chat.Add(Bob)
	chat.Add(John)
	// Send messages
	chat.Say(Bob, "Hello, Bob!")
	chat.Say(Alice, "Hello, Alice!")
	chat.SayAll("Hello, All!")
}

Conclusion

Mediator pattern is a good example of encapsulation logic into separate entity. It’s a complement to the Observer pattern. In real world applications though the logic can grow a lot, and turn this into God object antipattern.

Happy coding!

Code examples can be found in my GitHub repo pavel-fokin/go-patterns.