المراقب (نموذج تصميم)
{{عن|3=المراقب (توضيح)}}

نموذج '''المراقب''' {{إنج|Observer Pattern}} هو أحد [[نماذج التصميم (هندسة البرمجيات)|نماذج التصميم]] التي يدير فيها كائن يدعى باسم الهدف {{إنج|Subject}} قائمة من الكائنات الأخرى التي تعتمد عليه وتسمى هذه الكائنات بالمراقبين {{إنج|Observers}}، حيث يقوم بتنبيه هذه الكائنات عند حدوث تغيير في حالته والذي عادةً ما يحصل لدى استدعاء أحد الطرق الخاصة به.<ref>{{استشهاد بويب|عنوان=The Observer design pattern - Problem, Solution, and Applicability|مسار=http://w3sdesign.com/?gr=b07&ugr=proble|موقع=w3sDesign.com|تاريخ الوصول=2017-08-12| مسار أرشيف = https://web.archive.org/web/20180516133826/http://w3sdesign.com:80/?gr=b07&ugr=proble | تاريخ أرشيف = 16 مايو 2018 }}</ref><ref>{{استشهاد بويب|عنوان=The Observer design pattern - Structure and Collaboration|مسار=http://w3sdesign.com/?gr=b07&ugr=struct|موقع=w3sDesign.com|تاريخ الوصول=2017-08-12| مسار أرشيف = https://web.archive.org/web/20170821045813/http://w3sdesign.com/?gr=b07&ugr=struct | تاريخ أرشيف = 21 أغسطس 2017 }}</ref><ref>[https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations Comparison between different observer pattern implementations] Moshe Bindler, 2015 (Github) {{Webarchive|url=https://web.archive.org/web/20170302010910/https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations |date=02 مارس 2017}}</ref> يستخدم هذا النموذج بشكل رئيسي في تحقيق أنظمة التحكم بالأحداث الموزعة. كما يعتبر مكوناً رئيسياً من نموذج التصميم المعماري [[نمط وعرض ومتحكم|نمط-عرض-متحكم (MVC)]]. وقد استُخدم هذا النموذج لأول مرة في تصميم بيئة تطوير واجهة المستخدم المبنية على MVC والخاصة بلغة [[سمول توك]]. يستخدم نموذج المراقب بشكل واسع في العديد من المكتبات والنظم البرمجية بما في ذلك معظم أدوات تطوير واجهة المستخدم المرئية.

قد يسبب استخدام نموذج المراقب حدوث [[تسرب الذاكرة|تسريب في الذاكرة]] وتعرف هذه المشكلة باسم المستمع المختفي {{إنج|Lapsed Listener}}، يحدث ذلك بسبب الحاجة إلى تسجيل وإلغاء تسجيل المراقب بشكل صريح، وبما أن الهدف سيبقي مراجعاً قوية إلى قائمة مراقبيه فإنه سيمنع بذلك تدميرهم على سبيل المثال من قبل [[جمع القمامة (حاسوب)|جامع القمامة]]. يمكن حل هذه المشكلة عبر جعل الهدف يمتلك مراجعاً ضعيفة إلى مراقبيه.

== مكونات النموذج ==
[[ملف:Observer.svg|تصغير|500px|بدون|مخطط صفوف نموذج المراقب]]

== مثال ==
فيما يلي مثال بلغة [[جافا (لغة برمجة)|جافا]] يوضح كيفية استخدام نموذج المراقب، في هذا المثال تم قراءة الدخل من لوحة المفاتيح ومعالجة كل سطر كحدث. يستخدم هذا المثال الصفوف {{كود|java.util.Observer}} و{{كود|java.util.Observable}}. عند إدخال سلسلة محرفية عن طريق {{كود|System.in}} تُستدعى الطريقة {{كود|notifyObservers}} من أجل تنبيه كافة المراقبين إلى حدوث الحدث وذلك عن طريق استدعاء الطرق {{كود|update}} الخاصة بهم.

يتضمن الملف {{كود|MyApp.java}} الطريقة {{كود|main}} التي تستخدم لتشغيل الكود.

<syntaxhighlight lang="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();
        }
    }
}
</syntaxhighlight>
<syntaxhighlight lang="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 );
        }
    }
}
</syntaxhighlight>
<syntaxhighlight lang="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();
    }
}
</syntaxhighlight>
وهذا مثال آخر بلغة [[بايثون (توضيح)|بايثون]]:
<syntaxhighlight lang="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')
</syntaxhighlight>

== انظر أيضاً ==
* [[نماذج التصميم (هندسة البرمجيات)|نماذج التصميم]]
* [[نمط وعرض ومتحكم|نمط-عرض-متحكم]]
== مراجع ==
{{مراجع}}
{{روابط شقيقة}}
{{شريط بوابات|تقانة المعلومات|علم الحاسوب}}

{{أنماط تصميم البرمجيات}}

[[تصنيف:نماذج تصميم البرمجيات]]
نموذج المراقب  هو أحد نماذج التصميم التي يدير فيها كائن يدعى باسم الهدف  قائمة من الكائنات الأخرى التي تعتمد عليه وتسمى هذه الكائنات بالمراقبين ، حيث يقوم بتنبيه هذه الكائنات عند حدوث تغيير في حالته والذي عادةً ما يحصل لدى استدعاء أحد الطرق الخاصة به.Comparison between different observer pattern implementations Moshe Bindler, 2015 (Github)  يستخدم هذا النموذج بشكل رئيسي في تحقيق أنظمة التحكم بالأحداث الموزعة. كما يعتبر مكوناً رئيسياً من نموذج التصميم المعماري نمط-عرض-متحكم (MVC). وقد استُخدم هذا النموذج لأول مرة في تصميم بيئة تطوير واجهة المستخدم المبنية على MVC والخاصة بلغة سمول توك. يستخدم نموذج المراقب بشكل واسع في العديد من المكتبات والنظم البرمجية بما في ذلك معظم أدوات تطوير واجهة المستخدم المرئية.

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

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

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

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

/* 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();
        }
    }
}
/* 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 );
        }
    }
}
/* 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();
    }
}
وهذا مثال آخر بلغة بايثون:
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')

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

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