1. แพทเทิร์น Mediator คืออะไร

Mediator Pattern เป็นแพทเทิร์นในการออกแบบที่ลดการพึ่งพาตรงๆ ระหว่างอ็อบเจ็กต์โดยการโอนการสื่อสารไปยังอ็อบเจ็กต์ตัวกลาง ใน Mediator Pattern อ็อบเจ็กต์จะไม่สื่อสารโดยตรงกันและแทนนั้นจะสื่อสารผ่านอ็อบเจ็กต์ตัวกลาง

2. ลักษณะและข้อดีของ Mediator Pattern

ลักษณะและข้อดีของ Mediator Pattern มีดังนี้:

  • ลดความผูกพันตรงระหว่างอ็อบเจ็กต์ ลดความซับซ้อนของระบบ
  • ทำให้การสื่อสารระหว่างอ็อบเจ็กต์เป็นไปอย่างง่ายดายโดยมีอ็อบเจ็กต์ตัวกลางมาจัดการ
  • ควบคุมการโต้ตอบระหว่างอ็อบเจ็กต์ได้ในที่เดียว ทำให้ง่ายต่อการขยายและการบำรุงรักษา

3. ตัวอย่างจริงๆของ Mediator Pattern

Mediator Pattern มีการใช้งานในสถานการณ์ชีวิตจริงหลายอย่าง เช่นในระบบกำหนดเวลารถบนท่าอากาศยาน การดิสพาตซิเป็นตัวกลางขณะที่โมดูลต่างๆ เช่นเครื่องบินและการจราจรภายใต้ดิน ทำหน้าที่เป็นคลาสเพื่อสื่อสารและประสานงานผ่านการดิสพาตเชียวกัน

4. การนำ Mediator Pattern มาใช้ใน Golang

4.1 การนำเสนอแผนผังคลาส UML

ด้านล่างนี้คือแผนผังคลาส UML สำหรับ Mediator Pattern ใน Golang:

Mediator Pattern in Golang

4.2 การนำเสนอตัวอย่าง

ในตัวอย่างนี้ เราจะนำเสนอการปรับใช้แอปพลิเคชันห้องสนทนาง่ายๆ โดยใช้ Mediator Pattern เพื่อจัดการการสื่อสารระหว่างผู้ใช้งานท่านอื่นๆ

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 เราจะสร้างอ็อบเจ็กต์ตัวดิสพาตเฉพาะและอ็อบเจ็กต์ลูกค้าเฉพาะสองตัว จากนั้นลงทะเบียนอ็อบเจ็กต์ลูกค้าผ่านอ็อบเจ็กต์ตัวดิสพาตและทดสอบการสื่อสาร