2010-02-08 41 views
6

¿El patrón de diseño del observador ya está definido en STL (como java.util.Observer y java.util.Observable en Java)?Patrón de diseño del observador en C++

+2

presumiblemente como un ejemplo de la biblioteca estándar de otro idioma que tiene el patrón de observador construido en él. –

+0

sí Jeremy, eso es correcto – Lucas

+0

¿Es aceptable para usted? Si no, estaría dispuesto a publicar una implementación estándar sin impulso. –

Respuesta

6

Aquí hay una implementación de referencia (desde 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

Difícil de tomar en serio una implementación en C++ que use nombres de funciones de miembros ilegales como _Notify. –

+3

Aún así es válido C++. –

+1

Aparentemente tiene otros problemas también. Consulte la página de discusión: http://en.wikipedia.org/wiki/Talk:Observer_pattern#Implementation_flaw_in_C.2B.2B – Manuel

6

No, no lo hace. El C++ STL es mucho más pequeño que la biblioteca estándar de Java. Si está buscando algo para expandir en el STL que es compatible con casi todo, valdría la pena echar un vistazo a las bibliotecas de Boost. En este caso, puede consultar Boost.Signals que proporciona un modelo de señal/ranura.

18

No, pero Boost.Signals2 le ofrece algo similar.

+2

+1, Boost.Signals es genial. También revise Signals2 si tiene múltiples hilos. – Manuel

+1

Boost.Signals está en desuso, Boost.Signals2 se debe utilizar en su lugar. – shi

2

El Observer design pattern no está definido en la STL. Puede consultar el "Gang of four" Design Patterns book o una búsqueda en Google debe proporcionar suficientes detalles para implementarlo. Si esta pregunta no se responde pronto, publicaré un ejemplo rápido.

+0

O puede copiar y pegar la implementación de Wikipedia que alguien ha vinculado en otra respuesta – Manuel

+0

gracias! Las señales de Boost se ven interesantes.He usado Boost para la generación de números aleatorios, pero nunca para un patrón de observador o señales como lo llaman. De todos modos, creo que la evaluación del patrón de observadores GOF y Boost Signals es una buena idea, al menos para fines académicos. –

8

Según mi conocimiento va en C++, STL no tiene una implementación para el patrón Observer. Sin embargo, hubo una propuesta para Signal/Slot para la biblioteca estándar en TR2.

Hay muchas bibliotecas que proporcionan implementación para el patrón Observer. La biblioteca Qt es una de las pioneras. La biblioteca de impulso tiene una implementación (vea Boost :: Signals & Boost :: Signals2).

La biblioteca Poco C++ tiene una implementación clara del patrón de observador (vea el NotificationCenter).

libsigC++, cpp-events son algunas de las otras bibliotecas que proporcionan implementaciones de señal/ranura.

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

favor también ver los diagramas de flujo/UML http://www.patterns.pl/observer.html

Cuestiones relacionadas