2016-06-23 18 views
-1

Observer-Muster wird für Notify-Funktionalität verwendet, in der tatsächlichen Implementierung, können wenige klassifiziert blockieren Anrufe in der Benachrichtigungsfunktion. Grundsätzlich ist meine Frage, wie man vermeidet, dass die Benachrichtigungsfunktion blockiert wird. Denn wenn es aufgrund einer Klasse blockiert wird, blockiert es jeden zweiten Anruf. Wie im unteren Beispiel der update() Funktion wird eine Blockierung in der Klasse DivObserver durchgeführt.
unter Klasse Modified aus dem Original in eines der Klasse Sperrung Aussage zu zeigen:Observer Design Pattern-Klasse Ausgabe

class DivObserver: public Observer { 
    public: 
    DivObserver(Subject *mod, int div): Observer(mod, div){} 
     void update() 
     { 
     pthread_mutex_lock(); 
     /*blocking statement call*/ 
     pthread_mutex_unlock(); 
    } 
}; 

    -----------------------------------text book example---------------------      --------------- 

    #include <iostream> 
    #include <vector> 
    using namespace std; 

    class Subject { 
// 1. "independent" functionality 
    vector < class Observer * > views; // 3. Coupled only to "interface" 
    int value; 
    public: 
    void attach(Observer *obs) 
    { 
     views.push_back(obs); 
    } 
    void setVal(int val) 
    { 
     value = val; 
     notify(); 
    } 
    int getVal() { 
     return value; 
    } 
    void notify(); 
}; 

class Observer { 
    // 2. "dependent" functionality 
    Subject *model; 
    int denom; 
    public: 
    Observer(Subject *mod, int div) { 
     model = mod; 
     denom = div; 
     // 4. Observers register themselves with the Subject 
     model->attach(this); 
    } 
    virtual void update() = 0; 
    protected: 
    Subject *getSubject() { 
     return model; 
    } 
    int getDivisor() { 
     return denom; 
    } 
}; 

void Subject::notify() { 
    // 5. Publisher broadcasts 
    for (int i = 0; i < views.size(); i++) 
    views[i]->update(); 
} 

class DivObserver: public Observer { 
    public: 
    DivObserver(Subject *mod, int div): Observer(mod, div){} 
    void update() { 
     // 6. "Pull" information of interest 
     int v = getSubject()->getVal(), d = getDivisor(); 
     cout << v << " div " << d << " is " << v/d << '\n'; 
    } 
}; 

class ModObserver: public Observer { 
    public: 
    ModObserver(Subject *mod, int div): Observer(mod, div){} 
    void update() { 
     int v = getSubject()->getVal(), d = getDivisor(); 
     cout << v << " mod " << d << " is " << v % d << '\n'; 
    } 
}; 

int main() { 
    Subject subj; 
    DivObserver divObs1(&subj, 4); // 7. Client configures the number and 
    DivObserver divObs2(&subj, 3); // type of Observers 
    ModObserver modObs3(&subj, 3); 
    subj.setVal(14); 
} 
+0

Die offensichtlichste Lösung ist das Observable zu dokumentieren als "Beobachter sollten nicht blockieren. Wenn Ihr Beobachter blockiert, zu schlecht für Sie. Ich habe Sie gewarnt". –

+0

Ich werde es wieder auf Null setzen :) –

Antwort

1

Beobachter-Muster ein Problem auf Kosten der Schaffung von ein paar neuen Marke lösen. Das ist so typisch für praktisch jedes Muster da draußen.

Der Trick ist zu wissen, wie man das Verhalten des Musters steuert. Im Fall des Beobachters profitieren Sie davon, dass Sie effektiv eine Anzahl anderer Objekte zurückrufen können, ohne je von ihren Typen abhängig zu sein. Das ist ein guter Teil über den Beobachter. Der schlechte Teil ist, dass Sie, sobald Sie einen Rückruf durchführen, dem Objekt ausgeliefert sind, das Sie angerufen haben.

Ein weiteres Problem des Observer, das Entwickler oft vergessen, ist, dass der Abonnent sich abmelden muss, bevor er den Tod plant. Andernfalls hält das beobachtbare Objekt es in Systemen mit Garbage Collections am Leben. In Systemen mit expliziter Speicherdeallokation enthält das beobachtbare Objekt eine freie Referenz, was noch schlimmer ist.

Es gibt keinen schönen Ausweg aus diesen beiden Problemen. Sie sind die Signatur des Observer-Patterns genauso wie das Benachrichtigungskonzept. Wir könnten argumentieren, dass es möglich ist, die Implementierung in eine asynchrone Version umzuwandeln, sogar mit Timeouts usw. Aber das wäre weit außerhalb des Bereichs des Observable-Musters, und das wäre ein völlig anderes Design.

Endergebnis: Ja, wenn Beobachterobjekt blockiert, dann wird das beobachtbare Objekt blockiert und der Client, der einen Aufruf an das beobachtbare Objekt gesendet hat, wird ebenfalls blockiert.