2010-02-08 17 views
6

Ist das Observer-Entwurfsmuster bereits in STL definiert (wie java.util.Observer und java.util.Observable in Java)?Observer-Entwurfsmuster in C++

+2

Vermutlich als ein Beispiel eines anderen Standard-Bibliothek der Sprache, die die Beobachter-Muster hinein gebaut hat. –

+0

ja Jeremy, das ist korrekt – Lucas

+0

Ist Boost akzeptabel für Sie? Wenn nicht, wäre ich bereit, eine Standard-Nicht-Boost-Implementierung zu veröffentlichen. –

Antwort

6

Hier ist eine Referenzimplementierung (von 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

Es ist schwer, eine C++ - Implementierung ernst zu nehmen, die ungültige Mitgliedsfunktionsnamen wie _Notify verwendet. –

+3

Es ist immer noch gültig C++. –

+1

Offenbar hat es auch andere Probleme. Überprüfen Sie die Diskussionsseite: http://en.wikipedia.org/wiki/Talk:Observer_pattern#Implementation_flaw_in_C.2B.2B – Manuel

6

Nein, tut es nicht. Die C++ STL ist viel kleiner als die Standardbibliothek von Java. Wenn Sie nach etwas suchen, um die STL zu erweitern, die von fast allem unterstützt wird, sollten Sie sich die Boost-Bibliotheken ansehen. In diesem Fall sollten Sie sich Boost.Signals ansehen, das ein Signal/Slot-Modell bereitstellt.

18

Nein, aber Boost.Signals2 gibt Ihnen etwas Ähnliches.

+2

+1, Boost.Signals ist großartig. Überprüfen Sie auch Signale2, wenn Sie mehrere Threads haben. – Manuel

+1

Boost.Signals ist veraltet, stattdessen sollte Boost.Signals2 verwendet werden. – shi

2

Die Observer design pattern ist in der STL nicht definiert. Sie können auf die "Gang of four" Design Patterns book verweisen oder eine Google-Suche sollte genügend Details zur Verfügung stellen, um es zu implementieren. Wenn diese Frage nicht bald beantwortet wird, werde ich ein schnelles Beispiel veröffentlichen.

+0

Oder Sie können die Wikipedia-Implementierung, die jemand in einer anderen Antwort verknüpft hat, kopieren und einfügen – Manuel

+0

danke! Boost-Signale sehen interessant aus.Ich habe Boost für Zufallszahlengenerierung verwendet, aber nie für ein Beobachtermuster oder Signale, wie sie es nennen. Wie auch immer, ich denke, das GOF-Beobachtermuster und Boost-Signale zu bewerten, ist zumindest für akademische Zwecke eine gute Idee. –

8

Soweit mein Wissen in C++ geht, hat STL keine Implementierung für Observer-Muster. Es gab jedoch einen Vorschlag für Signal/Slot für die Standardbibliothek in TR2.

Es gibt viele Bibliotheken, die Implementierung für Observer-Muster Qt-Bibliothek als einer der Pioniere bietet. Die Boost-Bibliothek hat eine Implementierung (siehe Boost :: Signale & Boost :: Signals2).

Die Poco C++ - Bibliothek verfügt über eine übersichtliche Implementierung des Beobachtermusters (siehe NotificationCenter).

libsigC++, cpp-events sind einige der anderen Bibliotheken, die Signal/Slot-Implementierungen bereitstellen.

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

siehe auch UML/Flussdiagramme http://www.patterns.pl/observer.html