2016-06-23 5 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

나는 그것을 0으로 되돌릴 것이다 :) –

답변

1

옵저버 패턴은 새로운 사람 몇을 만드는 비용으로 하나의 문제를 해결한다. 이는 사실상 모든 패턴에있어 전형적입니다.

트릭은 패턴 동작을 제어하는 ​​방법을 알고있는 것입니다. 옵서버 (Observer)의 경우에는 유형에 의존하지 않고 효과적으로 다른 객체를 콜백 할 수 있다는 이점이 있습니다. 옵서버에 대한 좋은 부분입니다. 나쁜 부분은 일단 콜백 (call back)을하면, 당신이 호출 한 객체의 자비에 있다는 것입니다.

개발자가 종종 잊어 버리는 Observer에 대한 또 다른 문제는 구독자가 죽기 전에 가입을 취소해야한다는 것입니다. 그렇지 않으면 관찰 가능 객체가 가비지 콜렉션이있는 시스템에서이를 유지합니다. 메모리 할당을 명시 적으로 해제 한 시스템에서는 관찰 가능한 객체가 매달린 참조를 보유하게되며 이는 더욱 심각합니다.

이 두 가지 문제에서 좋은 방법은 없습니다. 그것들은 알림 개념만큼 Observer 패턴의 서명입니다. 우리는 심지어 타임 아웃 등으로도 구현을 비동기 버전으로 전환 할 수 있다고 주장 할 수 있습니다. 그러나 Observable 패턴의 범위를 벗어나면 완전히 다른 디자인이 될 것입니다.

결론 : 관찰자 객체 블록 인 경우 관찰 가능 객체가 차단되고 관찰 객체에 대한 호출을 한 클라이언트도 차단됩니다.