1. โครงแผนของแพทเทิร์น Chain of Responsibility

แพทเทิร์น Chain of Responsibility เป็นแพทเทิร์นการออกแบบที่เกี่ยวกับพฤติกรรมที่ช่วยในการแยกความผูกพันระหว่างผู้ส่งและผู้รับของคำขอ ที่เป็นการที่อนุญาตให้วัตถุหลาย ๆ ตัวทำหน้าที่กับคำขอนี้ แต่ล่ะตัวรับมีการเก็บอ้างอิงไปที่ตัวรับถัดไป และถ้าไม่สามารถจัดการคำขอได้ จะส่งคำขอต่อไปยังตัวรับถัดไปจนกว่าคำขอจะได้รับการจัดการหรือมาถึงจุดสิ้นสุดของโซ่

2. ลักษณะและคุณสมบัติของแพทเทิร์น Chain of Responsibility

ลักษณะและคุณสมบัติของแพทเทิร์น Chain of Responsibility มีดังนี้:

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

3. ตัวอย่างการประยุกต์ใช้ของแพทเทิร์น Chain of Responsibility

แพทเทิร์น Chain of Responsibility มีการประยุกต์ใช้ทางปฏิบัติหลายอย่าง เช่น:

  • การจัดการคำขอในแอปพลิเคชันเว็บ: สามารถนำมาใช้ในการจัดการกับประเภทคำขอต่าง ๆ เช่น การพิสูจน์ตัวตน, การบันทึกล็อก, และการตรวจสอบสิทธิ์
  • การจัดการข้อผิดพลาด: สามารถนำมาใช้ในการจัดการกับข้อผิดพลาด โดยที่แต่ล่ะตัวจัดการรับผิดชอบการจัดการกับประเภทข้อผิดพลาดเจาะจง และส่งข้อผิดพลาดต่อไปถ้าจำเป็น
  • การจัดการเหตุการณ์: สามารถนำมาใช้ในการจัดการกับประเภทต่าง ๆ ของเหตุการณ์ เช่น เหตุการณ์การคลิกของผู้ใช้, เหตุการณ์คำขอเครือข่าย และอื่น ๆ

4. การประยุกต์ใช้แพทเทิร์น Chain of Responsibility ใน Golang

4.1 แผนภาพคลาส UML

แพทเทิร์น Chain of Responsibility ใน Golang

4.2 การแนะนำตัวอย่าง

ในแผนภาพคลาส UML ด้านบน เราได้กำหนดอินเตอร์เฟซของตัวจัดการ (Handler) และตัวจัดการในรูปแบบเจาะจง (ConcreteHandler1 และ ConcreteHandler2) ลูกค้า (Client) ดำเนินการส่งคำขอโดยการเรียกเมธอด handleRequest ของตัวจัดการ

4.3 ขั้นตอนการประยุกต์ใช้ 1: กำหนดอินเตอร์เฟซตัวจัดการเจาะจง

type Handler interface {
    HandleRequest(request Request) error
    SetNext(handler Handler)
}

type Request interface {
    Condition bool
}

อินเตอร์เฟซตัวจัดการกำหนดเมธอด HandleRequest สำหรับการประมวลคำขอ และเมธอด SetNext สำหรับการกำหนดตัวจัดการถัดไป

4.4 ขั้นตอนการประยุกต์ใช้ 2: การสร้างคลาสตัวจัดการเจาะจง

type ConcreteHandler1 struct {
    next Handler
}

func (h *ConcreteHandler1) HandleRequest(request Request) error {
    // ตรรกะสำหรับการจัดการคำขอ
    if request.Condition {
        // โค้ดสำหรับการจัดการคำขอ
        return nil
    } else {
        if h.next != nil {
            return h.next.HandleRequest(request)
        }
        return errors.New("ไม่พบตัวจัดการ")
    }
}

func (h *ConcreteHandler1) SetNext(handler Handler) {
    h.next = handler
}

type ConcreteHandler2 struct {
    next Handler
}

func (h *ConcreteHandler2) HandleRequest(request Request) error {
    // ตรรกะสำหรับการจัดการคำขอ
    if request.Condition {
        // โค้ดสำหรับการจัดการคำขอ
        return nil
    } else {
        if h.next != nil {
            return h.next.HandleRequest(request)
        }
        return errors.New("ไม่พบตัวจัดการ")
    }
}

func (h *ConcreteHandler2) SetNext(handler Handler) {
    h.next = handler
}

คลาสตัวจัดการเจาะจงนี้นำอินเตอร์เฟซตัวจัดการมาใช้งานและโอเวอร์ไรด์เมธอด HandleRequest และ SetNext

4.5 ขั้นตอนการประยุกต์ใช้ 3: สร้างโซ่ของความรับผิดชอบ

handler1 := &ConcreteHandler1{}
handler2 := &ConcreteHandler2{}

handler1.SetNext(handler2)

โดยการสร้างตัวจัดการเจาะจงและกำหนดตัวจัดการถัดไป เราจึงสร้างโซ่ของความรับผิดชอบ

4.6 ขั้นตอนการประยุกต์ใช้ 4: รหัสลูกค้า

func main() {
    handler := &ConcreteHandler1{}

    // สร้างโซ่ของความรับผิดชอบ
    handler.SetNext(&ConcreteHandler2{})

    // ส่งคำขอ
    handler.HandleRequest(Request{Condition: true})
}

ในรหัสลูกค้า เราสร้างตัวจัดการเจาะจง, กำหนดตัวจัดการถัดไป และเรียกเมธอด HandleRequest เพื่อส่งคำขอ