2010-02-08 3 views
6

Является ли шаблон проектирования наблюдателя уже определенным в STL (Как java.util.Observer и java.util.Observable в Java)?Шаблон проектирования наблюдателя в C++

+2

Предположительно в качестве примера стандартной библиотеки другого языка, который имеет шаблон наблюдателя, встроенный в него. –

+0

Да Джереми, это правильно – Lucas

+0

Является ли повышение приемлемым для вас? Если бы не я, я был бы готов опубликовать стандартную невозбужденную реализацию. –

ответ

6

Вот эталонная реализация (от Wikipedia).

#include <iostream> 
#include <string> 
#include <map> 
#include <boost/foreach.hpp> 

class SupervisedString; 
class IObserver{ 
public: 
    virtual void handleEvent(const SupervisedString&) = 0; 
}; 


class SupervisedString{ // Observable class 
    std::string _str; 
    std::map<IObserver* const, IObserver* const> _observers; 

    typedef std::map<IObserver* const, IObserver* const>::value_type item; 

    void _Notify(){ 
     BOOST_FOREACH(item iter, _observers){ 
      iter.second->handleEvent(*this); 
     } 
    } 

public: 
    void add(IObserver& ref){ 
     _observers.insert(item(&ref, &ref)); 
    } 

    void remove(IObserver& ref){ 
     _observers.erase(&ref); 
    } 

    const std::string& get() const{ 
     return _str; 
    } 

    void reset(std::string str){ 
     _str = str; 
     _Notify(); 
    } 
}; 


class Reflector: public IObserver{ // Prints the observed string into std::cout 
public: 
    virtual void handleEvent(const SupervisedString& ref){ 
     std::cout<<ref.get()<<std::endl; 
    } 
}; 

class Counter: public IObserver{ // Prints the length of observed string into std::cout 
    virtual void handleEvent(const SupervisedString& ref){ 
     std::cout<<"length = "<<ref.get().length()<<std::endl; 
    } 
}; 

int main(){ 

    SupervisedString str; 
    Reflector refl; 
    Counter cnt; 

    str.add(refl); 
    str.reset("Hello, World!"); 
    std::cout<<std::endl; 

    str.remove(refl); 
    str.add (cnt); 
    str.reset("World, Hello!"); 
    std::cout<<std::endl; 

    return 0; 
} 
+9

Трудно серьезно относиться к реализации на C++, которая использует нелегальные имена функций-членов, такие как _Notify. – 2010-02-08 22:00:52

+3

Это все еще актуально C++. –

+1

Видимо, у него есть и другие проблемы. Проверьте страницу обсуждения: http://en.wikipedia.org/wiki/Talk:Observer_pattern#Implementation_flaw_in_C.2B.2B – Manuel

6

Нет, это не так. C++ STL намного меньше стандартной библиотеки Java. Если вы ищете что-то для расширения на STL, которое поддерживается почти всем, стоит взглянуть на библиотеки Boost. В этом случае вы можете посмотреть на Boost.Signals, который предоставляет модель сигнала/слота.

18

Нет, но Boost.Signals2 дает вам нечто подобное.

+2

+1, Boost.Signals замечательный. Также проверьте Signals2, если у вас несколько потоков. – Manuel

+1

Boost.Signals устарел, вместо этого следует использовать Boost.Signals2. – shi

2

The Observer design pattern не определен в STL. Вы можете обратиться к "Gang of four" Design Patterns book, или поиск Google должен предоставить достаточно подробностей для его реализации. Если этот вопрос не будет дан в ближайшее время, я отправлю вам быстрый пример.

+0

Или вы можете скопировать вставку реализации Википедии, которую кто-то связал в другом ответе – Manuel

+0

спасибо! Сигналы усиления выглядят интересными.Я использовал Boost для генерации случайных чисел, но никогда для шаблона наблюдателя или сигналов, как они его называют. Во всяком случае, я считаю, что оценка шаблона наблюдателя GOF и сигналов повышения уровня является хорошей идеей, по крайней мере, для академических целей. –

8

Насколько я знаю в C++, STL не имеет реализации для шаблона Observer. Однако было предложение для Signal/Slot для стандартной библиотеки в TR2.

Существует множество библиотек, которые обеспечивают реализацию библиотеки Qt для наблюдателя, являющейся одним из пионеров. Библиотека ускорения имеет реализацию (см. Boost :: Signals & Boost :: Signals2).

Библиотека Poco C++ имеет аккуратную реализацию шаблона наблюдателя (см. NotificationCenter).

libsigC++, cpp-events - это некоторые из других библиотек, которые обеспечивают реализацию сигналов/слотов.

2
#include <iostream> 
#include <string> 
#include <set> 
using namespace std; 
class Subject; 
class Observer { 
public: 
    virtual void update(Subject & subject) = 0; 
}; 
// also knows as Observable in literature 
class Subject 
{ 
    string state; 
    set<Observer*> observers; 
public: 
    void attachObserver(Observer *o) { observers.insert(o); } 
    void detachObserver(Observer *o) { observers.erase(o); } 
    void notifyObservers() 
    { 
    for (auto &o : observers) 
    { 
     o->update(*this); 
    } 
    } 
    string getState() { return state; } 
    void changeState(const string & s) 
    { 
    state = s; 
    notifyObservers(); 
    } 
}; 
class ObserverImpl : public Observer 
{ 
    string state; 
public: 
    void update(Subject & sbj) override 
    { 
    state = sbj.getState(); 
    } 
    string getState() { return state; } 
}; 
int main() 
{ 
    ObserverImpl a, b, c; 
    Subject subject; 
    subject.attachObserver(&a); 
    subject.attachObserver(&b); 
    subject.attachObserver(&c); 
    subject.changeState("Observer pattern"); 
    cout << a.getState() << endl; 
    cout << b.getState() << endl; 
    cout << c.getState() << endl; 
    return 0; 
} 

смотрите пожалуйста UML диаграмм/потоков http://www.patterns.pl/observer.html

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