2010-02-08 18 views
6

Czy wzór projektu obserwatora jest już zdefiniowany w STL (podobnie jak java.util.Observer i java.util.Observable w Javie)?Wzorzec wyglądu obserwatora w C++

+2

Przypuszczalnie jako przykład standardowej biblioteki innym języku, który posiada wbudowany wzorzec obserwatora do niego. –

+0

tak Jeremy, to jest poprawne – Lucas

+0

Czy akceptacja jest do przyjęcia? Jeśli nie, byłbym skłonny opublikować standardową implementację bez wspomagania. –

Odpowiedz

6

Oto implementacja referencyjna (od 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

Trudno traktować poważnie implementację C++, która używa niedozwolonych nazw funkcji elementów, takich jak _Notify. –

+3

To wciąż poprawne C++. –

+1

Podobno ma również inne problemy. Sprawdź stronę dyskusyjną: http://en.wikipedia.org/wiki/Talk:Observer_pattern#Implementation_flaw_in_C.2B.2B – Manuel

6

Nie, nie ma. Standard C++ STL jest znacznie mniejszy niż standardowa biblioteka Java. Jeśli szukasz czegoś, co można rozszerzyć na STL obsługiwanego prawie przez wszystko, warto rzucić okiem na biblioteki Boost. W takim przypadku warto przyjrzeć się Boost.Signals, która zapewnia model sygnału/szczeliny.

18

Nie, ale Boost.Signals2 podaje coś podobnego.

+2

+1, Boost.Signals jest świetny. Sprawdź także Signals2, jeśli masz wiele wątków. – Manuel

+1

Boost.Signals jest przestarzałe, zamiast tego należy użyć metody Boost.Signals2. – shi

2

The Observer design pattern nie jest zdefiniowany w STL. Możesz odwołać się do numeru "Gang of four" Design Patterns book, a wyszukiwarka Google powinna podać wystarczającą ilość szczegółów, aby go wdrożyć. Jeśli to pytanie nie zostanie udzielone wkrótce, opublikuję szybki przykład.

+0

Lub możesz skopiować i wkleić implementację Wikipedii, którą ktoś podłączył w innej odpowiedzi – Manuel

+0

dzięki! Sygnały doładowania wyglądają interesująco.Użyłem Boost do generowania liczb losowych, ale nigdy dla wzorca obserwatora lub sygnałów, jak go nazywają. W każdym razie sądzę, że ocena wzorca obserwatora GOF i sygnałów doładowania jest dobrym pomysłem, przynajmniej dla celów akademickich. –

8

O ile moja wiedza idzie w C++, STL nie ma implementacji dla wzorca Obserwatora. Pojawiła się jednak propozycja Signal/Slot dla biblioteki standardowej w TR2.

Istnieje wiele bibliotek, które zapewniają implementację biblioteki Qt wzorca obserwatora będącego jednym z pionierów. Biblioteka boost ma implementację (zobacz: Boost :: Signals & Boost :: Signals2).

Biblioteka Poco C++ ma zgrabną implementację wzorca obserwatora (zobacz Centrum NotificationCenter).

libsigC++, cpp-events to tylko niektóre z innych bibliotek, które udostępniają implementacje sygnału/szczeliny.

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; 
} 

proszę zobaczyć również diagramy UML/przepływ http://www.patterns.pl/observer.html

Powiązane problemy