1. Co to jest wzorzec mediatora

Wzorzec mediatora to wzorzec projektowy behawioralny, który redukuje bezpośrednie zależności między obiektami poprzez przeniesienie ich komunikacji do obiektu mediatora. W wzorcu mediatora obiekty nie komunikują się bezpośrednio, lecz poprzez obiekt mediatora.

2. Charakterystyka i Zalety wzorca mediatora

Charakterystyka i zalety wzorca mediatora to:

  • Redukuje bezpośrednie sprzężenie między obiektami, obniżając złożoność systemu.
  • Uprości komunikację między obiektami, pozwalając mediatorowi obsługiwać ich komunikację.
  • Centralizuje kontrolę interakcji między obiektami, ułatwiając rozszerzanie i konserwację.

3. Przykłady zastosowania wzorca mediatora w życiu codziennym

Wzorzec mediatora znajduje wiele zastosowań w scenariuszach życia codziennego. Na przykład w systemie planowania lotniska dyspozytor pełni rolę mediatora, podczas gdy różne moduły, takie jak samoloty i ruch naziemny, działają jako klasy kolegów komunikujące się i koordynujące poprzez dyspozytora.

4. Implementacja wzorca mediatora w języku Golang

4.1 Wprowadzenie do diagramu klas UML

Poniżej znajduje się diagram klas UML dla wzorca mediatora w języku Golang:

Wzorzec mediatora w języku Golang

4.2 Wprowadzenie przykładu

W tym przykładzie zaimplementujemy prostą aplikację czatu, wykorzystując wzorzec mediatora do zarządzania komunikacją między różnymi użytkownikami.

4.3 Krok implementacji 1: Zdefiniuj interfejs mediatora i konkretnego mediatora

Najpierw definiujemy interfejs mediatora i klasę konkretnego mediatora:

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 Krok implementacji 2: Zdefiniuj interfejs kolegi i klasy konkretnych kolegów

Następnie definiujemy interfejs kolegi oraz klasy konkretnych kolegów:

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 otrzymał wiadomość: %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 otrzymał wiadomość: %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 Krok implementacji 3: Zarządzanie kolegami w mediatorze

W konkretnej klasie mediatora musimy zaimplementować metodę registerColleague oraz metodę sendMessage do zarządzania komunikacją między klasami kolegów:

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

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

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

    colleagueA.sendMessage("Cześć, Świecie!")
    colleagueB.sendMessage("Cześć wszystkim!")
}

W funkcji main tworzymy konkretny obiekt mediatora oraz dwa konkretne obiekty kolegów, a następnie rejestrujemy obiekty kolegów poprzez obiekt mediatora i testujemy komunikację.