زند فریم ورک ۲ – Observer pattern
یکی از الگوهای طراحی نرم افزار Observer pattern است. در زند فریم ورک ۲ در قالب Event manager از این الگو استفاده شده است. این الگو به شما کمک میکند تا کلاس های مستقل تری داشته باشید. همانطور که در مطالب قبلی گفتم, کلاس ها هرچه قدر مستقل تر باشند امکان استفاده مجدد از آنها بیشتر و راحت تر است. همچنین باعث راحت تر شدن مدیریت کلاس ها خواهد شد.
برای تعریف این الگو نیاز به یک مثال ساده داریم :
فرض کنید که یک سامانه پیامکی دارید که قرار است بر اساس پیامک ورودی عملیاتی را بر روی اطلاعات وارد شده انجام دهد. در پاسخ تمام پیامک های ورودی یک عبارت خاص بر اساس زمان دریافت, به مخاطب ارسال می شود. از طرفی تمام پیامک های ورودی بررسی شده و اگر شامل عدد ۱ باشند در گروه خاصی قرار میگیرند.
در این مثال یک رویداد داریم : دریافت پیامک
و دو پردازش مختلف داریم :
۱ – ارسال عبارت خاص بر اساس زمان دریافت پیامک
۲ – بررسی متن پیامک ورودی و تشخیص عدد ۱
با استفاده از الگوی Observer Pattern میتوانیم این مثال را به شکل زیر حل کنیم:
یک کلاس Subject می سازیم که کار مدیریت رویداد ها و افزودن پردازش و حذف پردازش ها را بر عهده دارد.
دو کلاس برای پردازش ها در نظر میگیریم که هر دو از کلاسی با نام Observer ارث بری میکنند.(و یا Implement)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
<?php abstract class Observer { public function process(Subject $subject) { // Do something } } class Subject { protected $observers; protected $eventName; public function __construct() { $this->observers = array(); $this->eventName = null; } public function attach(Observer $observer) { $i = array_search($observer, $this->observers); if ($i === false) { $this->observers[] = $observer; } } public function detach(Observer $observer) { if (!empty($this->observers)) { $i = array_search($observer, $this->observers); if ($i !== false) { unset($this->observers[$i]); } } } public function getObservers() { return $this->observers; } public function getEvent() { return $this->eventName; } public function setEvent($eventName) { $this->eventName = $eventName; $this->trigger(); } protected function trigger() { if (!empty($this->observers)) { foreach ($this->observers as $observer) { $observer->process($this); } } } } class ReceiveSms extends Subject { protected $messageInfo; public function getReceivedMessage($reveivedMessageInfo) { $this->messageInfo = $reveivedMessageInfo; $this->setEvent('receive'); } public function getMessageInfo() { return $this->messageInfo; } } class AutoAnswer extends Observer { public function process(Subject $subject) { if ($subject->getEvent() == 'receive') { $messageInfo = $subject->getMessageInfo(); // Send auto answer by sms. } } } class FilterAnswer extends Observer { public function process(Subject $subject) { if ($subject->getEvent() == 'receive') { $messageInfo = $subject->getMessageInfo(); // Filter and move receiver number to a group } } } $receiveSms = new ReceiveSms(); $receiveSms->attach(new AutoAnswer()); $receiveSms->attach(new FilterAnswer()); $receiveSms->getReceivedMessage($reveivedMessageInfo); |
کلاس Observer می تواند استاندارد ما برای کلاس های وابسته به آن باشد. با تعریف این کلاس میخواهیم تمام کلاس هایی که از Observer ارث بری میکنند دارای یک استاندارد واحد باشند.
کلاس Subject وظیفه ی مدیریت, افزودن و حذف Observer ها را بر عهده دارد و در نهایت این کلاس رویداد ها را به Observer ها اعلام میکند فارغ از اینکه Observer ها چه تعداد هستند و یا چه کاری انجام میدهند.
کلاس ReceiveSms که ورودی ها را بررسی مینماید از Subject ارث بری مینماید تا بتواند هنگام رخ دادن رویدادی با استفاده از کلاس Subject آنرا به Observer ها منتقل کند. در واقع این کلاس سازنده رویداد هاییست که در Observer ها استفاده می شود.
کلاس AutoAnswer و FilterAnswer همان Observer های ما هستند که هر کدام وظیفه ی خاصی در قبال رخ دادن هر رویداد دارند و به صورت کاملا مستقل از هم عمل می نمایند.
در آخر Observer های ما بایستی با استفاده از متد attach به Subject معرفی شوند.
چه زمان از الگوی Observer استفاده کنیم؟
- زمانی که دو کلاس هر کدام کار مختلفی انجام میدهند اما در عین حال به هم وابسته هستند. با استفاده از این الگو دو کلاس وابستگی کمتری پیدا میکنندو میتوان از هر یک از کلاس ها به صورت جداگانه در پروژه های دیگر استفاده کرد.
- زمانی که یک تغییر در یک کلاس بایستی باعث تغییر در کلاس های دیگر شود.
- زمانی که یک کلاس بایستی به کلاس های دیگر رویدادی را گزارش دهد بدون اینکه از نوع کلاس های دیگر و تعدادشان اطلاعی داشته باشد.
در مباحث بعدی در رابطه با Event Manager بحث خواهیم کرد.
منابع :
www.oodesign.com/observer-pattern.html
http://www.dcs.bbk.ac.uk/~oded/OODP13/Sessions/Session6/Observer.pdf
https://en.wikipedia.org/wiki/Observer_pattern
http://sourcemaking.com/design_patterns/observer
محمد باقر رستمی
Latest posts by محمد باقر رستمی (see all)
- ماژول ZF2Base - 18 دی, 1394
- Singleton Pattern - 26 شهریور, 1394
- Prototype Pattern - 13 مرداد, 1394
جالب بود