1. Что такое паттерн Mediator

Паттерн Mediator - это поведенческий паттерн проектирования, который снижает прямые зависимости между объектами, перенося их взаимодействие на объект посредник. В паттерне Mediator объекты больше не общаются непосредственно друг с другом, а через объект посредника.

2. Характеристики и преимущества паттерна Mediator

Характеристики и преимущества паттерна Mediator следующие:

  • Снижает прямую связанность между объектами, снижая сложность системы.
  • Упрощает коммуникацию между объектами с помощью объекта-посредника, который управляет их взаимодействием.
  • Централизует контроль взаимодействия между объектами, облегчая расширение и обслуживание.

3. Реальные примеры паттерна Mediator

Паттерн Mediator имеет множество приложений в реальной жизни. Например, в системе планирования аэропорта диспетчер выступает в роли посредника, в то время как различные модули, такие как самолеты и наземное движение, являются классами коллег, которые общаются и координируются через диспетчера.

4. Реализация паттерна Mediator в Golang

4.1 Введение в UML-диаграмму классов

Ниже приведена UML-диаграмма классов для паттерна Mediator в Golang:

Mediator Pattern in Golang

4.2 Введение в пример

В этом примере мы реализуем простое приложение чата, используя паттерн Mediator для управления коммуникацией между разными пользователями.

4.3 Шаг 1 реализации: Определение интерфейса Mediator и конкретного посредника

Сначала мы определяем интерфейс посредника и класс конкретного посредника:

type Mediator interface {
    registerColleague(colleague Colleague)
    sendMessage(message string, colleague Colleague)
}

type ConcreteMediator struct {
    colleagues map[string]Colleague
}

func (m *ConcreteMediator) registerColleague(colleague Colleague) {
    m.colleagues[colleague.getName()] = colleague
}

func (m *ConcreteMediator) sendMessage(message string, colleague Colleague) {
    for _, c := range m.colleagues {
        if c != colleague {
            c.receiveMessage(message)
        }
    }
}

4.4 Шаг 2 реализации: Определение интерфейса Colleague и конкретных коллег

Затем мы определяем интерфейс коллеги и классы конкретных коллег:

type Colleague interface {
    receiveMessage(message string)
    sendMessage(message string)
    getName() string
}

type ConcreteColleagueA struct {
    mediator Mediator
    name     string
}

func (c *ConcreteColleagueA) receiveMessage(message string) {
    fmt.Printf("%s received message: %s\n", c.name, message)
}

func (c *ConcreteColleagueA) sendMessage(message string) {
    c.mediator.sendMessage(message, c)
}

func (c *ConcreteColleagueA) getName() string {
    return c.name
}

type ConcreteColleagueB struct {
    mediator Mediator
    name     string
}

func (c *ConcreteColleagueB) receiveMessage(message string) {
    fmt.Printf("%s received message: %s\n", c.name, message)
}

func (c *ConcreteColleagueB) sendMessage(message string) {
    c.mediator.sendMessage(message, c)
}

func (c *ConcreteColleagueB) getName() string {
    return c.name
}

4.5 Шаг 3 реализации: Управление коллегами в посреднике

В классе конкретного посредника необходимо реализовать метод registerColleague и метод sendMessage для управления коммуникацией между классами коллег:

func main() {
    mediator := &ConcreteMediator{
        colleagues: make(map[string]Colleague),
    }

    colleagueA := &ConcreteColleagueA{
        mediator: mediator,
        name:     "Colleague A",
    }
    colleagueB := &ConcreteColleagueB{
        mediator: mediator,
        name:     "Colleague B",
    }

    mediator.registerColleague(colleagueA)
    mediator.registerColleague(colleagueB)

    colleagueA.sendMessage("Hello, World!")
    colleagueB.sendMessage("Hi, there!")
}

В функции main создается конкретный объект посредника и два конкретных объекта коллег, затем регистрируются объекты коллег через объект посредника и выполняется тестирование коммуникации.