نمط المراقب هو نمط تصميم سلوكي. يتم استخدام نمط المراقب عندما تكون مهتمًا بحالة الكائن وتريد أن يتم إعلامك في كل مرة يتغير فيها. في نمط المراقب، يسمى الكائن الذي يلاحظ حالة كائن آخر المراقب، ويسمى الكائن المرصود الموضوع. وفقًا لقواعد GoF، فإن الهدف من نمط المراقب هو:
انسخ رمز الكود كما يلي:
تحديد علاقة تبعية رأس بأطراف بين الكائنات إذا تغيرت حالة الكائن، فسيتم إعلام الكائنات الأخرى ذات الصلة وتحديثها تلقائيًا.
تحتوي الموضوعات على مراقبين يجب إعلامهم عندما تتغير حالتهم. ولذلك، ينبغي أن تزود المراقبين بطرق تسجيل أنفسهم وإلغاء تسجيل أنفسهم. عندما يتغير الموضوع (المرصود)، فإنه يحتاج أيضًا إلى تضمين طريقة لإخطار جميع المراقبين. عند إخطار المراقبين، يمكنك دفع التحديثات أو توفير طريقة أخرى للحصول على التحديثات.
يجب أن يكون لدى المراقبين طريقة لتعيين كائن المراقب ويمكن للمراقب استخدامها لإعلامه بالتحديثات.
توفر JAVA طرقًا مدمجة لتنفيذ نمط المراقب وواجهات java.util.Observable وjava.util.Observer. ومع ذلك، فهي لا تستخدم على نطاق واسع جدا. نظرًا لأن هذا التنفيذ بسيط جدًا، فإننا لا نريد في معظم الأحيان أن تقوم الفئة الموسعة الأخيرة بتنفيذ نمط المراقب فقط، لأن فئات JAVA لا يمكنها أن ترث عدة مرات.
تستخدم خدمة رسائل خدمة رسائل Java (JMS) وضع المراقب ووضع الأوامر لتحقيق نشر البيانات والاشتراك فيها بين البرامج المختلفة.
يستخدم إطار التحكم في عرض نموذج MVC أيضًا نمط المراقب، حيث يتعامل مع النموذج باعتباره مراقبًا والعرض باعتباره مراقبًا. يمكن للمشاهدات تسجيل نفسها في النموذج لتلقي التغييرات على النموذج.
مثال على نمط المراقب
في هذا المثال سوف نكمل مناقشة بسيطة للموضوع، ويمكن للمراقبين التسجيل في هذا الموضوع. سيتم إخطار جميع المراقبين المسجلين بأي تغييرات ناتجة عن عمليات تقديم المحتوى حول هذا الموضوع.
بناءً على احتياجات مراقبي الموضوع، يتم تنفيذ واجهة الموضوع الأساسية. تحدد هذه الواجهة سلسلة من الأساليب المحددة التي يجب تنفيذها في فئة معينة تقوم بتنفيذ الواجهة لاحقًا.
انسخ رمز الكود كما يلي:
الحزمة com.journaldev.design.observer؛
موضوع الواجهة العامة {
// طرق تسجيل وإلغاء تسجيل المراقبين
تسجيل الفراغ العام (Observer obj)؛
إلغاء تسجيل الفراغ العام (Observer obj) ؛
// طريقة لإخطار المراقبين بالتغيير
public void notifyObservers();
// طريقة للحصول على التحديثات من الموضوع
كائن عام getUpdate(Observer obj);
}
الآن قم بإنشاء مراقب مرتبط. يحتاج إلى طريقة لربط الموضوع بالمراقب. يمكن للطرق الإضافية قبول إشعارات تغيير الموضوع.
انسخ رمز الكود كما يلي:
الحزمة com.journaldev.design.observer؛
مراقب الواجهة العامة {
// طريقة لتحديث المراقب، يستخدمها الموضوع
تحديث الفراغ العام ()؛
// إرفاق بالموضوع للمراقبة
public void setSubject(Subject sub);
}
تم إنشاء هذا الاتصال. الآن قم بتنفيذ الموضوع الملموس.
انسخ رمز الكود كما يلي:
الحزمة com.journaldev.design.observer؛
import java.util.ArrayList;
import java.util.List;
الطبقة العامة MyTopic تنفذ الموضوع {
قائمة خاصة<Observer> للمراقبين؛
رسالة سلسلة خاصة؛
تم تغيير القيمة المنطقية الخاصة؛
كائن نهائي خاص MUTEX= كائن جديد () ؛
موضوعي العام (){
this.observers=new ArrayList<>();
}
@تجاوز
تسجيل الفراغ العام (Observer obj) {
if(obj == null) throw new NullPointerException("Null Observer");
if(!observers.contains(obj)) Observers.add(obj);
}
@تجاوز
إلغاء تسجيل الفراغ العام (Observer obj) {
Observers.remove(obj);
}
@تجاوز
إعلام الفراغ العام () {
List<Observer> ObserversLocal = null;
// يتم استخدام المزامنة للتأكد من عدم إخطار أي مراقب مسجل بعد استلام الرسالة
متزامن (موتيكس) {
إذا (! تغير)
يعود؛
ObserversLocal = new ArrayList<>(this.observers);
this.changed=false;
}
لـ (Observer obj: ObserversLocal) {
obj.update();
}
}
@تجاوز
كائن عام getUpdate(Observer obj) {
إرجاع هذه الرسالة؛
}
// طريقة إرسال رسالة إلى الموضوع
postMessage العام الفارغ (سلسلة رسالة) {
System.out.println("تم إرسال الرسالة إلى الموضوع:"+msg);
this.message=msg;
this.changed=true;
notifyObservers();
}
}
يعد تنفيذ تسجيل وإلغاء تسجيل أساليب المراقب أمرًا بسيطًا للغاية. سيتم استخدام الطريقة الإضافية postMessage () من قبل العميل لإرسال رسالة سلسلة إلى هذا الموضوع. لاحظ أنه يتم استخدام المتغيرات المنطقية لتتبع التغييرات في حالة الموضوع وإخطار المراقبين بهذه التغييرات. يعد هذا المتغير ضروريًا لأنه إذا لم يكن هناك تحديث، ولكن قام شخص ما باستدعاء طريقة notifyObservers()، فلن يتمكن من إرسال معلومات إعلام الخطأ إلى المراقبين.
بالإضافة إلى ذلك، تجدر الإشارة إلى أنه يتم استخدام المزامنة في notifyObservers () للتأكد من أنه لا يمكن إرسال الإشعارات إلا إلى المراقبين المسجلين قبل نشر الرسالة حول الموضوع.
هنا هو تنفيذ المراقب. سوف يركزون دائمًا على كائن الموضوع.
انسخ رمز الكود كما يلي:
الحزمة com.journaldev.design.observer؛
الطبقة العامة MyTopicSubscriber تنفذ المراقب {
اسم سلسلة خاصة؛
موضوع خاص؛
MyTopicSubscriber العام (سلسلة نانومتر) {
this.name=nm;
}
@تجاوز
تحديث الفراغ العام () {
String msg = (String) subject.getUpdate(this);
إذا (الرسالة==فارغة){
System.out.println(name+":: لا توجد رسالة جديدة");
}آخر
System.out.println(name+":: الرسالة المستهلكة::"+msg);
}
@تجاوز
مجموعة الفراغ العام (الموضوع الفرعي) {
this.topic=sub;
}
}
لاحظ أن تنفيذ طريقة التحديث () يستخدم getUpdate () الخاص بالمراقب للتعامل مع الرسائل المحدثة. يجب تجنب تمرير الرسالة كمعلمة إلى طريقة التحديث () هنا.
فيما يلي برنامج اختبار بسيط للتحقق من تنفيذ فئة الموضوع.
انسخ رمز الكود كما يلي:
الحزمة com.journaldev.design.observer؛
الطبقة العامة ObserverPatternTest {
public static void main(String[] args) {
// إنشاء الموضوع
موضوع MyTopic = new MyTopic();
// إنشاء مراقبين
Observer obj1 = new MyTopicSubscriber("Obj1");
Observer obj2 = new MyTopicSubscriber("Obj2");
Observer obj3 = new MyTopicSubscriber("Obj3");
// تسجيل المراقبين للموضوع
theme.register(obj1);
theme.register(obj2);
theme.register(obj3);
// إرفاق المراقب بالموضوع
obj1.setSubject(topic);
obj2.setSubject(topic);
obj3.setSubject(topic);
//تحقق من توفر أي تحديث
obj1.update();
// أرسل الآن رسالة إلى الموضوع
theme.postMessage("رسالة جديدة");
}
}
هنا هو الإخراج أعلاه:
انسخ رمز الكود كما يلي:
Obj1:: لا توجد رسالة جديدة
تم إرسال الرسالة إلى الموضوع: رسالة جديدة
Obj1::استهلاك الرسالة::رسالة جديدة
Obj2::استهلاك الرسالة::رسالة جديدة
Obj3::استهلاك الرسالة::رسالة جديدة</pre>
مخطط UML لنمط المراقب
يُطلق على نمط المراقب أيضًا اسم نمط النشر والاشتراك. بعض التطبيقات المحددة في JAVA هي كما يلي:
1.java.util.EventListener في سوينغ
2.javax.servlet.http.HttpSessionBindingListener
3.javax.servlet.http.HttpSessionAttributeListener
ما سبق هو جميع أوضاع المراقب. آمل أن تكونوا مثل ذلك بالفعل. شارك مشاعرك في التعليقات أو يرجى مشاركتها مع الآخرين.