「PHP」觀察者模式模式


引言
 
  所屬:行為型模式,常用設計模式之一
 
    學習資料:
  • 《大話設計模式》程傑

 

模式概述
 
  觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有的觀察者對象,使他們能夠自動更新自己
 
  應用場景:當一個對象的改變需要同事改變其他對象的時候,而且它不知道具體有多少對象有待改變時,應該考慮使用觀察者模式。
  觀察者模式所作的工作其實就是在接觸耦合。讓耦合的雙方都依賴於抽象類,而不是依賴於具體,從而使得各自的變化都不會影響另一邊的變化
 
舉個栗子
 
    一家公司,用戶A喜歡玩游戲,用戶B喜歡看股票,上班不好好工作,經常被老板抓到,然后兩人想了一個方案:賄賂前台妹子,當老板到前台的時候囑咐前台妹子通知一下,也好不被抓到,那么程序如何設計呢。
       
 
     流程圖如下:
      
          

 

 

  
程序設計代碼:
1. 抽象觀察者,具體觀察者
<?php
/**
 * 抽象觀察者
 */
namespace observer_factory;

abstract class ObserverAbstract
{
    public abstract function update($news);
}
<?php

/**
 * 正在玩的員工
 */
namespace observer_factory;

class NbaObserver extends ObserverAbstract
{
    protected $name;

    protected $secretary;

    public function __construct(string $name, SubjectInterface $secretary)
    {
        $this->name = $name;

        $this->secretary = $secretary;
    }

    /**
     * 收到通知后的具體操作
     * @param $news
     */
    public function update($news)
    {
        echo $this->name.$news.'不要在玩了,繼續工作!';
    }
}
<?php
/**
 * 正在炒股的用戶
 */
namespace observer_factory;

class StockObserver extends ObserverAbstract
{
    protected $name;

    protected $secretary;

    public function __construct(string $name, SubjectInterface $secretary)
    {
        $this->name = $name;

        $this->secretary = $secretary;
    }
    /**
     * 收到通知后的具體操作
     * @param $news
     */
    public function update($news)
    {
        echo $this->name.$news.'不要在看股票,繼續工作!';
    }
}

 

2. 抽象通知者,具體通知者

<?php
/**
 * 抽象通知者
 */
namespace observer_factory;

interface SubjectInterface
{
    /**
     * 增加同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function attach($key, ObserverAbstract $observer);

    /**
     * 刪除同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function detach($key);

    /**
     * 發送消息
     */
    public function notify();

    /**
     * @param $news
     */
    public function secretaryNews($news);
}
<?php
/**
 * 通知者A
 */
namespace observer_factory;

class SubjectA implements SubjectInterface
{
    /**
     * 同事列表
     */
    private $list = [];

    private $news;

    /**
     * 增加同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function attach($key, ObserverAbstract $observer)
    {
        $this->list[$key] = $observer;
    }

    /**
     * 刪除同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function detach($key)
    {
        unset($this->list[$key]);
    }

    /**
     * 發送消息
     */
    public function notify()
    {
        foreach ($this->list AS $val) {
            $val->update($this->news);
        }
    }

    /**
     * @param $news
     */
    public function secretaryNews($news)
    {
        $this->news = $news;
    }
}
<?php

namespace observer_factory;

class SubjectB implements SubjectInterface
{
    /**
     * 同事列表
     */
    private $list = [];

    private $news;

    /**
     * 增加同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function attach($key, ObserverAbstract $observer)
    {
        $this->list[$key] = $observer;
    }

    /**
     * 刪除同事
     * @param ObserverAbstract $observer 針對抽象變成,減少了與具體類的耦合,也就是只有在繼承抽象觀察者的具體觀察者才可以使用
     */
    public function detach($key)
    {
        unset($this->list[$key]);
    }

    /**
     * 發送消息
     */
    public function notify()
    {
        foreach ($this->list AS $val) {
            $val->update($this->news);
        }
    }

    /**
     * @param $news
     */
    public function secretaryNews($news)
    {
        $this->news = $news;
    }
}

 

3. 測試

<?php

namespace observer_factory;

include '../autoload.php';

// 通知者A 進行通知
$tongzhizhe = new SubjectA();
$tongshi1 = new NbaObserver('用戶A', $tongzhizhe);
$tongshi2 = new StockObserver('用戶B', $tongzhizhe);

$tongzhizhe->attach('用戶A', $tongshi1);
$tongzhizhe->attach('用戶B', $tongshi2);

$tongzhizhe->secretaryNews('老板回來了');
$tongzhizhe->notify();

 

 
以下為源碼地址

  

  GitHub源碼地址:https://github.com/xiaobaoword/design_pattern/tree/master

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM