跳到主要内容

เนื้อหาภาษาไทย / 泰语内容

系统指南 内容已审核

Observer Pattern: แจ้งเตือนเมื่อมีการเปลี่ยนแปลง

บทความนี้แนะนำ Observer Pattern ซึ่งเป็น Design Pattern ที่ช่วยให้ Object หนึ่ง (Subject) สามารถแจ้งเตือนการเปลี่ยนแปลงสถานะไปยัง Object อื่นๆ (Observers) ได้ โ...

Observer Pattern: แจ้งเตือนเมื่อมีการเปลี่ยนแปลง

ในโลกของการพัฒนาซอฟต์แวร์, เรามักเจอกับสถานการณ์ที่ Object หนึ่ง (Subject) มีการเปลี่ยนแปลงสถานะ และเราต้องการให้ Object อื่นๆ (Observers) รับรู้ถึงการเปลี่ยนแปลงนั้นทันที Observer Pattern เป็น Design Pattern ที่ช่วยแก้ปัญหานี้ได้อย่างสวยงาม โดยทำให้ Subject สามารถแจ้งเตือน Observers ได้โดยไม่ต้องรู้รายละเอียดภายในของ Observers แต่ละตัว

พูดง่ายๆ ก็คือ Observer Pattern คือระบบแจ้งเตือน (Notification System) ที่ Subject เป็นผู้ส่งสัญญาณ และ Observers เป็นผู้รับสัญญาณ เมื่อ Subject มีการเปลี่ยนแปลงอะไรก็ตาม Observers ที่ลงทะเบียนไว้จะได้รับการแจ้งเตือนและสามารถตอบสนองต่อการเปลี่ยนแปลงนั้นได้

ความหมายของ Observer Pattern

Observer Pattern เป็น Design Pattern ประเภท Behavioral Pattern ซึ่งเน้นที่ความสัมพันธ์ระหว่าง Object ต่างๆ โดยมีองค์ประกอบหลักดังนี้:

  • Subject: Object ที่มีการเปลี่ยนแปลงสถานะ และเป็นผู้แจ้งเตือนไปยัง Observers
  • Observer: Object ที่รอรับการแจ้งเตือนจาก Subject และตอบสนองต่อการเปลี่ยนแปลง

ความสัมพันธ์ระหว่าง Subject และ Observer เป็นแบบ "One-to-Many" นั่นคือ Subject หนึ่งตัวสามารถมี Observers ได้หลายตัว และ Observers แต่ละตัวสามารถติดตาม Subject ได้หลายตัวเช่นกัน

Observer Pattern ช่วยลด Dependency ระหว่าง Subject และ Observers เนื่องจาก Subject ไม่จำเป็นต้องรู้รายละเอียดการทำงานของ Observers แต่ละตัว เพียงแค่รู้ว่า Observers เหล่านั้นได้ลงทะเบียนเพื่อรับการแจ้งเตือนเท่านั้น

การ Implement Observer Pattern

ในการ Implement Observer Pattern ใน PHP เราจะต้องสร้าง Interface สำหรับ Observer และ Subject จากนั้นสร้าง Concrete Class ที่ Implement Interface เหล่านั้น

1. สร้าง Observer Interface:

<?php

interface Observer {
  public function update(Subject $subject);
}

Interface นี้กำหนด Method `update()` ซึ่ง Observers ทุกตัวจะต้อง Implement Method นี้จะถูกเรียกเมื่อ Subject มีการเปลี่ยนแปลง

2. สร้าง Subject Interface:

<?php

interface Subject {
  public function attach(Observer $observer);
  public function detach(Observer $observer);
  public function notify();
}

Interface นี้กำหนด Method `attach()` สำหรับเพิ่ม Observer, `detach()` สำหรับลบ Observer, และ `notify()` สำหรับแจ้งเตือน Observers ทั้งหมด

3. สร้าง Concrete Subject Class:

<?php

class ConcreteSubject implements Subject {
  private $observers = [];
  private $state;

  public function attach(Observer $observer) {
    $this->observers[] = $observer;
  }

  public function detach(Observer $observer) {
    $key = array_search($observer, $this->observers, true);
    if ($key !== false) {
      unset($this->observers[$key]);
    }
  }

  public function notify() {
    foreach ($this->observers as $observer) {
      $observer->update($this);
    }
  }

  public function setState($state) {
    $this->state = $state;
    $this->notify();
  }

  public function getState() {
    return $this->state;
  }
}

Class นี้ Implement Subject Interface และเก็บรายชื่อ Observers ไว้ใน Array เมื่อมีการเปลี่ยนแปลงสถานะ (State) จะเรียก Method `notify()` เพื่อแจ้งเตือน Observers ทั้งหมด

4. สร้าง Concrete Observer Class:

<?php

class ConcreteObserver implements Observer {
  private $name;

  public function __construct($name) {
    $this->name = $name;
  }

  public function update(Subject $subject) {
    echo "Observer {$this->name}: Subject's state changed to " . $subject->getState() . "<br>";
  }
}

Class นี้ Implement Observer Interface และเมื่อได้รับการแจ้งเตือน (Method `update()` ถูกเรียก) จะแสดงข้อความว่า Subject มีการเปลี่ยนแปลงสถานะ

ตัวอย่างการใช้งาน:

<?php

// สร้าง Subject
$subject = new ConcreteSubject();

// สร้าง Observers
$observer1 = new ConcreteObserver("Observer 1");
$observer2 = new ConcreteObserver("Observer 2");

// ลงทะเบียน Observers กับ Subject
$subject->attach($observer1);
$subject->attach($observer2);

// เปลี่ยนสถานะของ Subject
$subject->setState("New State");

// ยกเลิกการลงทะเบียน Observer ตัวหนึ่ง
$subject->detach($observer1);

// เปลี่ยนสถานะของ Subject อีกครั้ง
$subject->setState("Another State");

ผลลัพธ์ที่ได้:

Observer Observer 1: Subject's state changed to New State<br>
Observer Observer 2: Subject's state changed to New State<br>
Observer Observer 2: Subject's state changed to Another State<br>

จากตัวอย่างจะเห็นว่า เมื่อเราเปลี่ยนสถานะของ Subject, Observers ที่ลงทะเบียนไว้จะได้รับการแจ้งเตือนและแสดงข้อความตามสถานะใหม่ของ Subject

ข้อดีและข้อเสียของ Observer Pattern

ข้อดี:

  • ลด Dependency: Subject และ Observers ไม่จำเป็นต้องรู้รายละเอียดภายในของกันและกัน
  • Loose Coupling: สามารถเพิ่มหรือลบ Observers ได้โดยไม่กระทบต่อ Subject
  • Reusability: สามารถนำ Observers กลับมาใช้ใหม่กับ Subjects อื่นๆ ได้
  • Broadcast Communication: Subject สามารถแจ้งเตือน Observers ได้หลายตัวพร้อมกัน

ข้อเสีย:

  • Unexpected Updates: Observers อาจได้รับการแจ้งเตือนที่ไม่เกี่ยวข้องกับตนเอง
  • Performance Issues: หากมี Observers จำนวนมาก การแจ้งเตือนอาจทำให้เกิดปัญหาด้านประสิทธิภาพ
  • Difficult to Debug: เนื่องจากความสัมพันธ์ที่ซับซ้อนระหว่าง Subject และ Observers อาจทำให้การ Debug เป็นเรื่องยาก

Trade-offs และแนวปฏิบัติที่ดี:

  • การจัดการลำดับการแจ้งเตือน: พิจารณาว่าลำดับการแจ้งเตือน Observer มีความสำคัญหรือไม่ ถ้ามี อาจต้องกำหนดลำดับความสำคัญให้กับ Observer แต่ละตัว
  • การจัดการข้อผิดพลาด: หากการ `update()` ของ Observer ตัวใดตัวหนึ่งเกิดข้อผิดพลาด ควรมีกลไกในการจัดการข้อผิดพลาดนั้น เพื่อไม่ให้กระทบต่อ Observer ตัวอื่นๆ
  • การใช้ Message Queue: สำหรับระบบที่มี Observer จำนวนมาก การใช้ Message Queue เข้ามาช่วยในการจัดการการแจ้งเตือน จะช่วยลดภาระของ Subject และเพิ่มความสามารถในการ Scalability ของระบบ
  • Push vs. Pull Model: ในตัวอย่างข้างต้น เราใช้ Push Model คือ Subject ส่งข้อมูล (State) ไปให้ Observer แต่เราสามารถใช้ Pull Model ได้เช่นกัน โดย Observer จะต้องเรียก Method ของ Subject เพื่อดึงข้อมูลที่ต้องการเอง การเลือกว่าจะใช้ Push หรือ Pull Model ขึ้นอยู่กับความเหมาะสมของแต่ละสถานการณ์

Observer Pattern เป็น Design Pattern ที่มีประโยชน์อย่างมากในการสร้างระบบที่ต้องการความยืดหยุ่นและลด Dependency ระหว่าง Object ต่างๆ การทำความเข้าใจและนำไปประยุกต์ใช้จะช่วยให้คุณสามารถสร้างซอฟต์แวร์ที่มีคุณภาพและง่ายต่อการบำรุงรักษาได้

ในบทความถัดไป เราจะมาเรียนรู้เกี่ยวกับอีกหนึ่ง Design Pattern ที่น่าสนใจ นั่นคือ Factory Pattern ซึ่งเป็น Pattern ที่ช่วยในการสร้าง Object โดยไม่ต้องระบุ Class ที่ต้องการสร้างโดยตรง

Office.in.th Custom Service

想基于此结构开发或定制系统?

Office.in.th 承接企业级 Web Application、API Integration 以及政府/企业管理系统的设计与开发,并提供长期支持。

查看软件开发服务