۱۴۰۰/۰۲/۲۹

دیزاین پترن Observer در php

Observer Pattern in Php ۱۳۹۸/۰۶/۱۹

دیزاین پترن ها راه حال های قابل تکرار برای چالش های رایج در طراحی نرم افزار هستند.یکی از این دیزاین پترن ها observer pattern است .که معمولا برای ارتباط یک به چند بین اشیا کاربرد دارد.به گونه ای که تغییر در یک شی نیاز به تغییر در چند شی دارد.

اگر شما ار فریم ورک ها مطرح php استفاده کرده باشید .حتما از این دیزاین پترن به نوعی استفاده کرده اید بطور مثال در فریم ورک سیموفنی هنگام استفاده از EventDispatcher از الگوی طراحی observer استفاده میکنید.در فریم ورک  مدرن دیگر php مانند لاراول هم در هنگام استفاده از شنونده های از این الگو طراحی استفاده میشود.اگر نحوه پیاده سازی این دیزاین پترن را بدانیم در صورت بروز مشکل راحت تر میتوانیم آن مشکل را برطرف کنیم.

الگوی Observer یک وابستگی یک به چند است بدین معنی که وقتی یک شیء تغییر میکند بطور خودکار  به همه اشیاء وابسته به ان اطلاع داده میشود و انها به روز میشوند.

پیاده سازی observer pattern در php

کتابخانه استاندارد PHP اینترفیس ها ای به نام SplObserver و SplSubject  به عنوان یک تمپلیت استاندارد برای اجرای الگو Observer  فراهم کرده است.

SplSubject Interface

interface SplSubject  {

        /**
         * Attach an SplObserve
         * @param SplObserver $observer
         * @return void 
         */
        public function attach (SplObserver $observer);

        /**
         * Detach an observer
         * @param SplObserver $observe
         * @return void
         */
        public function detach (SplObserver $observer);

        /**
         * Notify an observer
         * @return void 
         */
        public function notify ();

}

SplObserver Interface

interface SplObserver  {

        /**
         * Receive update from subject
         * @param SplSubject $subject
         * @return void 
         */
        public function update (SplSubject $subject);

}

متد attach() راهی را فراهم می کند که بتوان یک مشاهده کنند یا observer  را با موضوع publisher اضافه یا ثیت کرد.و متد detach() برای خالی کردن حافظه اشغال شده بوسیله ناشر استفاده میشود.و متد notify() به همه observers  های مشترک تغییرات را اطلاع میدهد.و بعد از آن با فرخوانی متد update() همه آنها را به روز رسانی میکند.

Observable/Subject/Publisher Implemenation

use SplSubject;
use SplObserver;
class Publisher implements SplSubject
{
/**
* @var array
*/
protected $linkedList = array();

/**
* @var array
*/
protected $observers = array();

/**
*
* @param string
*/

protected $name;

/**
*
* @param string
*/

protected $event;

public function __construct($name)
{

$this->name = $name;
}

/**
* Associate an observer
*
* @param SplObserver $observer
* @return Publisher;
*/

public function attach(SplObserver $observer)
{
$observerKey = spl_object_hash($observer);
$this->observers[$observerKey] = $observer;
$this->linkedList[$observerKey] = $observer->getPriority();
arsort($this->linkedList);
}

/**
* @param SplObserver $observer
* @return void
*/
public function detach(SplObserver $observer)
{
$observerKey = spl_object_hash($observer);
unset($this->observers[$observerKey]);
unset($this->linkedList[$observerKey]);
}

/**
* @return void
*/
public function notify()
{
foreach ($this->linkedList as $key => $value) {
$this->observers[$key]->update($this);
}
}

/**
* Set or update event
*
* @param $event
* @return void
*/
public function setEvent($event)
{
$this->event = $event;
$this->notify();
}

/**
* @return string
*/
public function getEvent()
{
return $this->event;
}

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

}

در ابتدا متد attach() را تعریف میکنیم که یک نمونه از observer  را به عنوان آرگومانت قبول میکند.دقیقا همانطور که از نام آن مشخص است یک observer  را با یک موضوع مرتیط میکند.و متد detach() برای جدا کردن یک observer از موضوع پیاده سازی شده است .

متد notify()  بوسیله یک حلقه لیست پیوندی میشود.و کلیدهای subscriber’s  ها را ذخیره میکند.از این کلید برای observer  مربوطه استفاده میشود.و سپس متد update() را برای به روز رسانی ها فرخوانی می کند.

توجه داشته باشید که لیست پیوندی مرتب شده است تا اطمینان حاصل شود که ابتدا به  observer یا ناظر که بالاترین اولویت را دارد  اطلاع داده میشود.

 متد setEvent()  مقداری رویدادی را که میخواهیم اطلاع دهیم بعنوان ارگومانت قبول میکند.و بعد از آن متد notify() را صدا مکیند که این متد هم متد update()  را برای به روز رسانی فرخوانی میکند.

Observer/Subscriber Implementation

use SplObserver;
use SplSubject;

class Observer implements SplObserver
{
    /**
     * @var  string
     */
    protected $name;

    /**
     * @var int
     */
    protected $priority = 0;


    /**
     * Accepts observer name and priority, default to zero
     */
    public function __construct($name, $priority=0)
    {
        $this->name =$name;
        $this->priority =$priority;
    }

    /**
     * Receive update from subject and print result
     *
     * @param SplSubject $publisher
     * @return void
     */
    public function update(SplSubject $publisher){

        print_r($this->name.': '. $publisher->getEvent(). PHP_EOL);

    }

    /**
     * Get observer priority
     * 
     * @return int
     */
    public  function getPriority(){
        return $this->priority;
    }

}

نمونه observer  دو آرگومانت را قبول میکند .نام observer و اولویت,سپس متد  update() اجرا میشود.که این متد SplSubject  را بعنوان آرگومانت می پذیرد.و بعد  متد getEvent()  را فرخوانی میکند و نتیجه را به کنسول بازمیگرداند.

Observer-Pattern-Php

طریقه استفاده از observer pattern در php

فرض کنید در یک پرتال اداری باید یک پیام به همه کارمندان  ارسال کنید و بعضی از کارمندان در مرخصی هستند.و فقط از طریق ایمیل میتوان به آنها دسترسی داشت علاوه بر این ما میخواهیم یک فیدبک از این رویداد در داشبورد مستقر در دفتر داشته باشیم.

برای این کار از الگو طراحی observer استفاده میکنیم .

$noty = new Publisher('NotificationPublisher');
$email = new Observer('EmailObserver', 50);
$slack = new Observer('SlackObserver', 10);
$dashboard = new Observer('DashboardObserver',30);

// Attach observers$noty->attach($email);
$noty->attach($slack);
$noty->attach($dashboard);// Set event that will be broadcasted
$noty->setEvent("Server LNX109 is going down");

خروجی

EmailObserver: Server LNX109 is going down
DashboardObserver: Server LNX109 is going down
SlackObserver: Server LNX109 is going down

در یک سناریو واقعی شاید شما بخواهید از یک abstract class از هر دو Publisher  و Observer استفاده کنید که قابل تعمیم یا extended باشد.


رای :

Observer

دیزاین پترن

Observer-Pattern

php

SplObserver

SplSubject

ارسال نظر
Copyright © All right reserved.