بسم الله الرحمن الرحيم
كل عام وانتم بخير بمناسبة حلول عيد الأضحي المبارك وكل عام وانتم بخير واعاده الله علينا وعليكم بالخير واليمن والبركة
الحلقة الثالثة : Observer Pattern أو نمط المراقب
يعبر هذا النمط عن حالات المراقبه بحيث يمكننا وضع كائن ما تحت المراقبة ويكون هذا الكائن Observable Object اي كائن قابل للمراقبة من خلال
كائن أخر ( أو أكثر ) يلعب دور المراقب لذلك يطلق علي هذا الكائن Observer اي المراقب
لكن ما هي الحاجة لهذا النمط ؟
بكل صراحة لا أخفي عليكم قولا أن هذا النمط يكون تطبيقة أكثر فاعلية في برامج سطح المكتب desktop application
إلا أننا يمكننا إستخدامه في الحالات التالية :
- تدوين الأخطأ error reporting
- التغلب علي حالات فقد قاعدة بيانات MySQL لبعض الخصائص مثل المنبهات triggers
مثال تطبيقي بسيط لتوضيح فكرة هذا النمط
نريد رصد الأخطأ الناتجة من البرنامج بحيث يتم تدوينها في التالي :
- ملف متابعة log file
- وأيضا يتم إرسالها إلي البريد الإليكتروني الخاص بك
- وأيضا يتم تسجيل هذا الخطأ في جدول بقاعدة البيانات (اسم الجدول SolutionErrors)
- طباعة هذا الخطأ بالمتصفح
الحل:
تابع المخطط التالي

الجزء الأول : الكائن الذي يتم مراقبته Observable Object
من المخطط السابق يتضح لنا أننا قمنا بعمل فئة باسم Observable وهي بمثابة الفئة الأم للكائنات التي يتم وضعها تحت المراقبة
وتتميز الفئة Observable بالتالي :
- هي فئة مجردة abstract class
- تحتوي علي مصفوفة باسم observers تحمل الكائنات التي تقوم بمراقبة هذا الكائن
( وكل عنصر بهذه المصفوفة يعبر عن كائن من نوع الفئة الأم Observer كما سنري لاحقا )
- وظيفة باسم addObserver تمكننا من إضافة كائن للمراقبة (Observer Object) في المصفوفة observers
( وهي وظيفة داخلية internal or package method يتم إستدعائها من خلال كائنات المراقبة )
- وظيفة باسم notifyObservers تقوم باستدعاء الوظيفة update الخاص بكل كائن يقوم بمراقبة هذا الكائن (وهذه الكائنات هي محتوي المصفوفة observers )
( وهي وظيفة خاصة يتم توريثها protected method يتم إستدعائها من خلال الكائن الذي يتم مراقبته )
وهي كالتالي
<?php
/**
* Base Observerable class
*/
class Observable {
/**
* private
* $observers an array of Observer objects to notify
*/
var $observers = array();
/**
* addObserver
*
* Register the reference to an object object
* @return void
*/
function addObserver( &$observer ) {
$this->observers[] = &$observer;
}
/**
* notifyObservers
*
* Calls the update() function using the reference to each
* registered observer - used by children of Observable
* @return void
*/
function notifyObservers() {
$observersCount = count($this->observers);
for($i=0; $i<$observersCount; $i++) {
$this->observers[$i]->update();
}
}
}
?>وكما يتضح من المخطط السابق أننا قمنا بعمل فئة باسم SolutionError ترث هذه الفئة من الفئة Observable
اي أننا يمكننا إجراء مراقبة لكائنات هذه الفئة
وتتميز الفئة SolutionError بالتالي :
- تحتوي علي متغير باسم message يتم تحميله بقيمة رسالة الخطأ
- تحتوي علي الوظيفة addError يتم من خلالها تحميل قيمة رسالة الخطأ , ثم يتم تبليغ الكائنات التي تراقب هذا الكائن
بأن هذا الكائن حدث به تغير ما من خلال إستدعاء الوظيفة notifyObservers
وهي كما يلي
<?php
/**
* Class SolutionError
*/
class SolutionError extends Observable {
var $message;
/**
* addError
*
* add error and notifies observers
* @return void
*/
function addError($message) {
$this->message = $message;
// Call the parent function to notify all observers
$this->notifyObservers();
}
}
?>الجزء الثاني : الكائنات المراقبة Observers Object
من المخطط السابق يتضح لنا أننا قمنا بعمل فئة باسم Observer وهي بمثابة الفئة الأم للكائنات التي تلعب دور المراقب
وتتميز الفئة Observer بالتالي :
- هي فئة مجردة abstract class
- تحتوي علي متغير باسم subject يعبر عن الكائن الذي يتم مراقبته
- الوظيفة update (وهي وظيفة مجردة abstract method اي يجب إعادة كتابتها في الفئات المشتقة من هذه الفئة )
يتم إستدعائها بشكل تلقائي من الكائن الذي يتم مراقبته ( من خلال إستدعاء الوظيفة notifyObservers )
وهي كما يلي
<?php
/**
* Base Observer class
*/
class Observer {
/**
* private
* $subject a child of class Observable that we're observing
*/
var $subject;
/**
* Constructs the Observer
* @param $subject the object to observe
*/
function Observer( &$subject ) {
$this->subject = &$subject;
// Register this object so subject can notify it
$subject->addObserver($this);
}
/**
* update
*
* Abstract function implemented by children to respond to
* changes in Observable subject
* @return void
*/
function update() {
trigger_error ('Update not implemented');
}
}
?>ومن بعد ذلك تمكننا من عمل فئات المراقبة المشتقة من الفئة Observer
وهم كالتالي :
1- BrowserObserver
وهذه الفئة خاصة بمراقبة الأخطاء , ثم في حالة وجود خطأ يتم تدوينها بالمتصفح
وهي كما يلي
<?php
/**
* Class BrowserObserver
*/
class BrowserObserver extends Observer {
/**
* Implement the parent update() method
* write the error message into the browser
* @return void
*/
function update () {
echo $this->subject->message;
}
}
?>2- EmailObserver
وهذه الفئة خاصة بمراقبة الأخطاء , ثم في حالة وجود خطأ يتم إرسال هذا الخطأ إلي البريد الإليكتروني
وهي كما يلي
<?php
/**
* Class EmailObserver
*/
class EmailObserver extends Observer {
/**
* Implement the parent update() method
* send the error message into the administrator email
* @return void
*/
function update () {
@mail("a_elhussein@hotmail.com", "email error observer", $this->subject->message );
}
}
?>3- LogFileObserver
وهذه الفئة خاصة بمراقبة الأخطاء , ثم في حالة وجود خطأ يتم تدوينها في ملف المتابعة باسم log.txt
وهي كما يلي
<?php
/**
* Class LogFileObserver
*/
class LogFileObserver extends Observer {
/**
* Implement the parent update() method
* write the error message into the log file
* @return void
*/
function update () {
$fp = @fopen("log.txt" , "ab+");
fwrite($fp, date("Y-m-d") . "\t" . $this->subject->message . "\r\n" );
}
}
?>4- DBObserver
وهذه الفئة خاصة بمراقبة الأخطاء , ثم في حالة وجود خطأ يتم تسجيله في جدول SolutionErrors الموجود بقاعدة البيانات test لمزود قاعدة البيانات mysql
وهي كما يلي
<?php
/**
* Class DBObserver
*/
class DBObserver extends Observer {
/**
* Implement the parent update() method
* add new field into the database table [SolutionErrors]
* @return void
*/
function update () {
// Connect into mysql database server
$link = @mysql_pconnect("localhost" ,"root" ,"");
if( is_resource($link) ) {
// Activate database
if( @mysql_select_db("test" ,$link) ) {
$errMessage = str_replace("'", "''", $this->subject->message);
$sql = "insert into SolutionErrors values(CURDATE(),'$errMessage')";
mysql_query($sql , $link );
}
}
}
}
?>إلي اللقاء بإذن الله مع نمط جديد
وبالله التوفيق
والسلام عليكم ورحمة الله وبركاته
