شارك المقالة
شرح Observer Design Pattern بالتفصيل مع مثال عملي في Java

شرح Observer Design Pattern بالتفصيل مع مثال عملي في Java

شرح Observer Design Pattern بالتفصيل مع مثال عملي في Java


إذا كنت تبحث عن طريقة احترافية لربط أجزاء النظام ببعضها دون تعقيد أو ترابط قوي، فإن Observer Design Pattern هو أحد أهم الأنماط التي يجب أن تتقنها.

هذا النمط يُستخدم بكثرة في الأنظمة التي تعتمد على الأحداث (Event-Driven Systems)، مثل تطبيقات الإشعارات، أنظمة الدفع، وتطبيقات الطقس.

فكر فيه ببساطة: عندما يحدث حدث معين، يتم إشعار مجموعة من الكائنات بشكل تلقائي دون الحاجة لربط مباشر بينها.

ما هو Observer Design Pattern؟

يُعتبر Observer Design Pattern أحد أنماط التصميم السلوكية (Behavioral Design Patterns)، ويعتمد على فكرة وجود كائن رئيسي يسمى Subject، ومجموعة من الكائنات الأخرى تسمى Observers.

عند حدوث تغيير في حالة الـ Subject، يتم إشعار جميع الـ Observers تلقائيًا.

هذا النمط يحقق مبدأ مهم في البرمجة وهو Loose Coupling، أي تقليل الترابط بين الكائنات.

فكرة النمط بطريقة بسيطة

تخيل أن لديك قائمة بريدية (Newsletter)، وعند نشر منتج جديد:

– يتم إرسال إشعار لكل المشتركين – بدون معرفة تفاصيل كل مشترك

هذا بالضبط ما يقدمه Observer Design Pattern.

مثال بدون استخدام Observer Pattern

في هذا المثال، الكود مرتبط بشكل مباشر بكل العمليات:

public class PaymentProcessor {
    public void processPayment() {
        System.out.println("Processing payment...");
        sendEmailConfirmation();
        updateFinancialRecords();
        sendSMSNotification();
    }

    private void sendEmailConfirmation() {
        System.out.println("Sending email confirmation...");
    }

    private void updateFinancialRecords() {
        System.out.println("Updating financial records...");
    }

    private void sendSMSNotification() {
        System.out.println("Sending SMS notification...");
    }

    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();
        processor.processPayment();
    }
}

المشكلة في الطريقة التقليدية

– ترابط قوي بين الكود (Tight Coupling) – صعوبة إضافة ميزات جديدة – الحاجة لتعديل الكود الأساسي في كل مرة

مثال باستخدام Observer Design Pattern

هنا نقوم بفصل المنطق باستخدام Subject و Observer:

import java.util.ArrayList;
import java.util.List;

// Observer
interface Observer {
    void update();
}

// Subject
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// Subject Implementation
class PaymentProcessor implements Subject {
    private List<Observer> observers = new ArrayList<>();

    public void processPayment() {
        System.out.println("Processing payment...");
        notifyObservers();
    }

    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

// Observers
class EmailNotification implements Observer {
    public void update() {
        System.out.println("Sending email confirmation...");
    }
}

class FinancialRecordUpdater implements Observer {
    public void update() {
        System.out.println("Updating financial records...");
    }
}

class SMSNotification implements Observer {
    public void update() {
        System.out.println("Sending SMS notification...");
    }
}

// Main
public class Main {
    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();

        processor.registerObserver(new EmailNotification());
        processor.registerObserver(new FinancialRecordUpdater());
        processor.registerObserver(new SMSNotification());

        processor.processPayment();
    }
}

تحسين الكود باستخدام Enum

يمكنك تنظيم الكود بشكل أفضل باستخدام enum لإدارة أنواع المراقبين:

enum ObserverType {
    EMAIL,
    FINANCIAL,
    SMS
}

يساعد هذا في إدارة المراقبين بشكل أكثر احترافية خاصة في الأنظمة الكبيرة.

شرح كيف يعمل Observer Pattern

– نقوم بإنشاء Observer Interface يحتوي على update – نقوم بإنشاء Subject Interface لإدارة الاشتراك – نقوم بإنشاء كلاس رئيسي (مثل PaymentProcessor) – نحتفظ بقائمة من Observers – عند حدوث حدث (Event) نقوم باستدعاء notifyObservers

بهذا الشكل يتم تنفيذ جميع العمليات المرتبطة بالحدث بشكل تلقائي.

الفرق بين الطريقتين

قابلية التوسع
يمكن إضافة Observers بدون تعديل الكود الأساسي.

تقليل التبعيات
Subject لا يعرف تفاصيل Observers.

تنظيم الكود
كل كلاس مسؤول عن وظيفة محددة.

مميزات Observer Design Pattern

مرونة عالية
إضافة أو حذف Observers بسهولة.

فصل الاهتمامات
كل جزء من النظام مستقل.

إعادة الاستخدام
يمكن استخدام نفس Observers في أكثر من سيناريو.

دعم الأنظمة التفاعلية
مثالي للتطبيقات المعتمدة على الأحداث.

عيوب Observer Design Pattern

تعقيد زائد
قد يصبح الكود معقدًا مع زيادة عدد Observers.

صعوبة التتبع
من الصعب معرفة من تم استدعاؤه عند حدوث حدث.

مشاكل الأداء
إذا كان هناك عدد كبير من Observers قد يتأثر الأداء.

متى تستخدم Observer Design Pattern؟

– عند بناء أنظمة تعتمد على الأحداث (Event Driven) – عند الحاجة لإشعار عدة كائنات بتغيير معين – في أنظمة الإشعارات (Notifications) – في تطبيقات الطقس أو التحديثات المباشرة – في أنظمة الدفع والتقارير

أفضل استخدامات النمط

– أنظمة الإشعارات – تطبيقات التواصل – أنظمة الدفع الإلكتروني – أنظمة المراقبة (Monitoring Systems) – التطبيقات التفاعلية

الخلاصة

يُعد Observer Design Pattern من أهم الأنماط التي تساعدك على بناء أنظمة مرنة وقابلة للتوسع.

يسمح لك بفصل الكود وتقليل التبعيات، مما يجعل التطبيق أسهل في الصيانة والتطوير.

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

ببساطة: إذا كان لديك حدث معين وتريد تنفيذ عدة عمليات عند حدوثه، فإن هذا النمط هو الحل الأفضل.

مثل: عند إضافة منتج جديد → يتم إرسال إشعار لكل المستخدمين، أو عند تغيير حالة معينة → يتم تحديث جميع الأنظمة المرتبطة.

لمزيد من المقالات شاهد : شرح Proxy Design Pattern بالتفصيل في Java مثال عملي مع المميزات والعيوب
شاهد أيضًا
مقالات ذات صلة
حل مشكله Execution failed for task ‘:app:compileDebugJavaWithJavac’

حل مشكله Execution failed for task ‘:app:compileDebugJavaWithJavac’رسالة الخطأ تعني أن عملية تجميع كود Java أثناء…

استخدام JWT وMiddleware في Node.js لإنشاء أدوار Admin وUser بأمان

أفضل طرق تحسين أداء نظام Roles في No de.js: Admin أم Userإنشاء Roles لمشروعك في…

كيفية طباعة الرقم الاكبر بين رقمين باستخدام لغة برولوج | print the largest number prolog code

  لغة prolog واحده من اكثر لغات البرمجة المعقدة و code برولوج ليس من الاكواد…

🚫 مانع الإعلانات مفعل

يجب إيقاف مانع الإعلانات لاستكمال تصفح الموقع