October 24, 2013

PHP - Design Pattern - Observer

Nguồn: http://mydevelopedworld.files.wordpress.com/2013/03/observer-pattern-uml.png
Đã lâu lắm rồi mới ngồi viết lại đề tài "Design Pattern", hôm nay mình giới thiệu thêm một cái Design Pattern nữa cũng rất hấp dẫn và lôi cuốn, và nó cũng làm mình mất không ít thời gian tìm hiểu - Observer Design Pattern. Với mẫu thiết kế này, nó sẽ giúp bạn xây dựng mô hình lập trình hướng sự kiện - Event-Driven Programming (EDP) - và trong ví dụ này của mình cũng sẽ dùng vấn đề này để demo cho mẫu thiết kế Observer

Khi nào dùng Observer

Observer là mẫu thiết kế dành cho việc một đối tượng khi thay đổi trạng thái của bản thân nó thì các đối tượng đính kèm theo cũng sẽ được thông báo. Trong trường hợp của EDP, một đối tượng phát nổ (trigger) lên một sự kiện, thì các listener được đính kèm sẽ lắng nghe và thực hiện (nếu có).

Observer built-in PHP 

Trong PHP 5.1, đã bổ sung cho mình 1 thư viện khủng lồ mà ít người xài tới - SPL (Standard Php Language) - và trong thư viện này có hỗ trợ cho chúng ta 2 interface SplSubject SplObserver. Thật tế thì đây chỉ là 2 interface thôi, việc cài đặt để nó thành đúng thiết kế pattern Observer vẫn là thuộc vào lập trình viên.

Demo ứng dụng Observer - EDP

1 - Class Event
class Event
{
  protected $_observers;
  protected $_eventName;
  protected $_embedParams;

  public function __construct()
  {
    $this->_observers = [];
  }

  public function attach(Listener $observer)
  {
    if (array_search($observer, $this->_observers) === FALSE)
    {
      $this->_observers[] = $observer;
    }
  }

  public function detach(Listener $observer)
  {
    if (!count($this->_observers) && 
      ($idx = array_search($observer, $this->_observers)) !== FALSE)
    {
      unset($this->_observers[$idx]);
    }
  }

  public function notify()
  {
    if (count($this->_observers))
    {
      foreach ($this->_observers as $observer)
      {
        $observer->update($this);
      }
    }
  }
    
  public function trigger($eventName, $params = [])
  {
    $this->_eventName = $eventName;
    $this->_embedParams = $params;
    $this->notify();
  }
    
  public function getEventName()
  {
    return $this->_eventName;
  }
    
  public function getParams()
  {
    return $this->_embedParams;
  }
}

2 - Class Listen
class Listener 
{
  public function __construct(Event $event)
  {
    $event->attach($this);
  }
    
  public function update(Event $event)
  {
    if($event->getEventName() == 'EventName')
    {
      $this->execEventName($event->getParams());
    }
  }
  public function execEventName($params = NULL)
  {
    var_dump($params);
  }
}

3 - Sử dụng Event - Listen
$event = new Event;
$listener = new Listener($event);
$event->trigger('EventName', ['k' => 'val']);

No comments:

Post a Comment