2016-06-23 2 views
-1

шаблон наблюдателя используется для уведомления о функциональности, в реальной реализации несколько классов могут блокировать вызовы в функции уведомления. В основном, мой вопрос заключается в том, как избежать блокировки функции уведомления. Потому что, если он получает блокируется из-за одного класса, он блокирует каждый другой вызов. Как показано ниже, функция update() делает блокировку в классе DivObserver.
Модифицированный ниже класса от оригинала, чтобы показать блокирующий заявление в одном из класса:образец класса шаблона наблюдателя

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

Наиболее очевидным решением является документирование наблюдаемого как «Наблюдатели не должны блокироваться. Если ваш наблюдатель блокирует, слишком плохо для вас. Я предупреждал вас». –

+0

Я верну его обратно к нулю :) –

ответ

1

Паттерн наблюдатель решает одну проблему за счет создания пару фирменных новых. Это типично для практически всех образцов.

Трюк заключается в том, чтобы знать, как контролировать поведение шаблона. В случае с наблюдателем вы получаете выгоду от того, что вы можете эффективно перезвонить несколько других объектов, не завися от их типов. Это хорошая часть об Observer. Плохая часть состоит в том, что после того, как вы поместите звонок назад, вы находитесь во власти объекта, которого вы вызвали.

Еще одна проблема Observer, о которой разработчики часто забывают, заключается в том, что абонент должен отказаться от подписки, прежде чем он планирует умереть. В противном случае наблюдаемый объект будет поддерживать его в системах с сборками мусора. В системах с явным освобождением памяти наблюдаемый объект будет удерживать свисающую ссылку, что еще хуже.

Существует нет хорошего выхода из этих двух проблем. Они являются сигнатурой шаблона Observer так же, как концепция уведомления. Мы можем утверждать, что можно превратить реализацию в асинхронную версию, даже с тайм-аутами и т. Д. Но это будет за пределами рамки Observable, и это будет совершенно другой дизайн.

Итог: Да, если блоки объектов наблюдателя, то наблюдаемый объект блокируется, и клиент, который поместил вызов наблюдаемому объекту, также заблокирован.

Смежные вопросы