المراقب (نموذج تصميم)

نموذج **المراقب**  هو أحد نماذج التصميم التي يدير فيها كائن يدعى باسم الهدف  قائمة من الكائنات الأخرى التي تعتمد عليه وتسمى هذه الكائنات بالمراقبين ، حيث يقوم بتنبيه هذه الكائنات عند حدوث تغيير في حالته والذي عادةً ما يحصل لدى استدعاء أحد الطرق الخاصة به. يستخدم هذا النموذج بشكل رئيسي في تحقيق أنظمة التحكم بالأحداث الموزعة. كما يعتبر مكوناً رئيسياً من نموذج التصميم المعماري نمط-عرض-متحكم (MVC). وقد استُخدم هذا النموذج لأول مرة في تصميم بيئة تطوير واجهة المستخدم المبنية على MVC والخاصة بلغة سمول توك. يستخدم نموذج المراقب بشكل واسع في العديد من المكتبات والنظم البرمجية بما في ذلك معظم أدوات تطوير واجهة المستخدم المرئية.

قد يسبب استخدام نموذج المراقب حدوث تسريب في الذاكرة وتعرف هذه المشكلة باسم المستمع المختفي ، يحدث ذلك بسبب الحاجة إلى تسجيل وإلغاء تسجيل المراقب بشكل صريح، وبما أن الهدف سيبقي مراجعاً قوية إلى قائمة مراقبيه فإنه سيمنع بذلك تدميرهم على سبيل المثال من قبل جامع القمامة. يمكن حل هذه المشكلة عبر جعل الهدف يمتلك مراجعاً ضعيفة إلى مراقبيه.

## مكونات النموذج
تصغير|500px|بدون|مخطط صفوف نموذج المراقب

## مثال
فيما يلي مثال بلغة جافا يوضح كيفية استخدام نموذج المراقب، في هذا المثال تم قراءة الدخل من لوحة المفاتيح ومعالجة كل سطر كحدث. يستخدم هذا المثال الصفوف  و. عند إدخال سلسلة محرفية عن طريق  تُستدعى الطريقة  من أجل تنبيه كافة المراقبين إلى حدوث الحدث وذلك عن طريق استدعاء الطرق  الخاصة بهم.

يتضمن الملف  الطريقة  التي تستخدم لتشغيل الكود.


```java
/* EventSource.java : اسم الملف */
package org.wikipedia.obs;

import java.util.Observable;          //تضمين مكتبة المراقب
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class EventSource extends Observable implements Runnable {
    @Override
    public void run() {
        try {
            final InputStreamReader isr = new InputStreamReader(System.in);
            final BufferedReader br = new BufferedReader(isr);
            while (true) {
                String response = br.readLine();
                setChanged();
                notifyObservers(response);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```


```java
/* ResponseHandler.java : اسم الملف */

package org.wikipedia.obs;

import java.util.Observable;
import java.util.Observer;  /* هذا هو معالج الأحداث */

public class ResponseHandler implements Observer {
    private String resp;
    public void update(Observable obj, Object arg) {
        if (arg instanceof String) {
            resp = (String) arg;
            System.out.println("\nReceived Response: " + resp );
        }
    }
}
```


```java
/* MyApp.java : اسم الملف */
/* البرنامج الرئيسي هنا */

package org.wikipedia.obs;

public class MyApp {
    public static void main(String[] args) {
        System.out.println("Enter Text >");

        // مصدر الأحداث - قراءة الدخل من مجرى الدخل الرئيسي
        final EventSource eventSource = new EventSource();

        // أنشئ مراقب
        final ResponseHandler responseHandler = new ResponseHandler();

        // سجل المراقب في قائمة مراقبي الأحداث
        eventSource.addObserver(responseHandler);

        // شغل خيط مصدر الأحداث
        Thread thread = new Thread(eventSource);
        thread.start();
    }
}
```

وهذا مثال آخر بلغة بايثون:

```python
class Observable(object):
  def __init__(self):
    self.__observers = []
  def registerObserver(self, observer):
    self.__observers.append(observer)
  def notifyObservers(self, *args, **kwargs):
    for observer in self.__observers:
      observer.notify(self, *args, **kwargs)

class Observer(object):
  def __init__(self, observable):
    observable.registerObserver(self)
  def notify(self, observable, *args, **kwargs):
    print 'Got', args, kwargs, 'From', observable

subject = Observable()
observer = Observer(subject)
subject.notifyObservers('test')
```


## انظر أيضاً
* نماذج التصميم
* نمط-عرض-متحكم
## مراجع

تصنيف:نماذج تصميم البرمجيات