c ++中的观察者模式

时间:2011-01-22 03:54:16

标签: c++ design-patterns

我对观察者模式有点麻烦 我有一个饮料类,使用装饰精细。 我正在尝试实现观察者,以便在这种情况下让观察者(例如手机/文本消息)知道订单何时完成。我不会包括饮料/装饰师课程,因为他们工作正常。

在主要我会做这样的事情:

Subject mySubject = new Subject();
Observer myObserver1 = new Observer1();
Observer myObserver2 = new Observer2();

// register observers
mySubject.Register(myObserver1);
mySubject.Register(myObserver2);

mySubject.Notify("message 1");
mySubject.Notify("message 2");

我有一个主题类,观察者,电话行为类和一个手机1,手机2类......

这是主题课

#ifndef _SUBJECT_
#define _SUBJECT_

//#include "Starbuzz.h"
//#include "Starbuzz2.h"
#include "Observer.h"
#include <list>

namespace CoffeeHouse {
namespace Observers {


class Subject  {


private:
std::list< Observer* > observers;

public:
Subject();
~Subject();

void Subject::Register(Observer observer)
{

//if (!observers.(observer))
//{

observers.insert(observer);
}
//}

//void Unregister(Observer observer)
//{
// if observer is in the list, remove
//if (observers.Contains(observer))
//{
//observers.Remove(observer);
//}
//}

void Notify(std::string message)
{
//need loop
Observer observer;
observer.update(message);


}
//}
//}

//void Subject::registerObserver( Observer* o ) { assert( o );
    //_observers.push_front(o);
//}
//void Subject::removeObserver( Observer* o ) { assert( o );
//  _observers.remove(o);
//}
//void Subject::notifyObservers() const {
    //for( std::list< Observer* >::iterator iterator = _observers.begin();   _observers.end() != iterator; ++iterator ) {
        //Observer* observer = *iterator;
        //observer->update(message);
    //}
//}
};
} // namespace Observer
} 


#endif

这是观察者类

#ifndef _OBSERVER_
#define _OBSERVER_

#include <string>

namespace CoffeeHouse {
namespace Observers {

class Subject;

class Observer {

//public: virtual ~Observer() = 0; 

public: virtual void Update(std::string message) = 0;
};

这是手机行为类

#ifndef _PHONEBEHAVIOR_
#define _PHONEBEHAVIOR_

namespace CoffeeHouse {
namespace Observer {

class PhoneBehavior {
public: virtual void Update() const = 0;
};
protected: virtual ~PhoneBehavior() = 0 {

};


};

} // namespace Observer
} //

这是手机1

#ifndef _CELLPHONE1_
#define _CELLPHONE1_

namespace CoffeeHouse {
namespace Observer {
include<iostream>
class CellPhone1: public Observer, public PhoneBehavior {
public: 
    CellPhone1();
    ~CellPhone1();
virtual void Update(std::string message)
 {
   std::cout << "CellPhone1: " << message;
}
};

} // namespace Observer
} //

#endif

这里是我得到的错误..

error C2259: 'CoffeeHouse::Observers::Observer' : cannot instantiate abstract class
1>        due to following members:
1>        'void CoffeeHouse::Observers::Observer::update(std::string)' : is abstract
see declaration of 'CoffeeHouse::Observers::Observer::update'
error C2661: 'std::list<_Ty>::insert' : no overloaded function takes 1 arguments
with[_Ty=CoffeeHouse::Observers::Observer *

error C2259: 'CoffeeHouse::Observers::Observer' : cannot instantiate abstract class
due to following members:
'void CoffeeHouse::Observers::Observer::update(std::string)' : is abstract
observer.h(15) : see declaration of 'CoffeeHouse::Observers::Observer::update

当我点击错误“无法实例化抽象类”时,我需要:

void Subject::Register(Observer observer)

据我所知,抽象类的制作使得它们无法实例化!

我怎么能做更新呢?有什么更好的建议吗?

我感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

我看到的问题:

  • 您使用命名空间和类 在PhoneBehavior中调用Observer 和CellPhone1类源文件。
  • 在CellPhone1类源文件中 不要#include <string>或使用 void Update(string message)
  • 中字符串的std命名空间
  • 在PhoneBehavior类源文件中 virtual void update()应该有 可能有一个资本“U”留下来 符合您的编码风格和 因为这就是它的名字 CellPhone1类源文件。
  • 在CellPhone1类源文件中,您有Cout <<"CellPhone1:" + message);。它应该是std::cout << "CellPhone1: " << message;
  • 在CellPhone1类源文件中,您需要#include <iostream>
  • 您在PhoneBehavior类源文件中有太多的结束括号。并且只有与class PhoneBehavior的左大括号对应的右括号后面应该有分号。

编辑:当我说“类源文件”时,我假设您的项目设置为CellPhone1.cpp,PhoneBehavior.cpp文件基于您提出问题的方式。

答案 1 :(得分:1)

一个错误是Subject :: Register当前正在使用Observer对象,而不是指向Observer的指针。这意味着您正在尝试实例化一个抽象对象,这是非法的。

答案 2 :(得分:0)

您可以通过此操作使一切可见:

https://simmesimme.github.io/tutorials/2015/09/20/signal-slot

#ifndef SIGNAL_H
#define SIGNAL_H

#include <functional>
#include <map>

//! A signal object may call multiple slots with the same
//! signature. You can connect functions to the signal which will be
//! called when the emit() method on the signal object is invoked. Any
//! argument passed to emit() will be passed to the given functions.
template <typename... Args>
class signal
{
public:
  //! Default constructor.
  signal(): m_slots(), m_current_id(0) {}

  //! Copy constructor. (deleted)
  signal(signal const& other) = delete;

  //! Assignment operator. (deleted)
  signal& operator=(signal const& other) = delete;

  //! Connects a member function to this signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! int id = s.connect_member(&myclass, MyClass::method);
  //! @endcode
  //!
  //! @param[in] instance Pointer to the instance to connect.
  //! @param[in] func Pointer to the member func to connect.
  //! @return id of object connected, to be used to disconnect.
  template <typename T>
  int connect_member(T *inst, void (T::*func)(Args...))
  {
    return connect([=](Args... args) {(inst->*func)(args...);});
  }

  //! Connects a const member function to this signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! int id = s.connect_member(&myclass, MyClass::method);
  //! @endcode
  //!
  //! @param[in] instance Pointer to the instance to connect.
  //! @param[in] func Pointer to the member func to connect.
  //! @return id of object connected, to be used to disconnect.
  template <typename T>
  int connect_member(T *inst, void (T::*func)(Args...) const)
  {
    return connect([=](Args... args) { (inst->*func)(args...);});
  }

  //! Connects a std::function function wrapper to this signal.
  //!
  //! This method can be used to adapt many kinds of callable objects
  //! to a signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! std::function<void()> f = std::bind(&signal_utest::test0, this);
  //! int id = s.connect(f);
  //! @endcode
  //!
  //! @param[in] slot Function object invoked on emit().
  //! @return id of object connected, to be used to disconnect.
  int connect(std::function<void(Args...)> const& slot) const
  {
    m_slots.insert(std::make_pair(++m_current_id, slot));
    return m_current_id;
  }

  //! Disconnects a previously connected function.
  //!
  //! @param[in] id Id returned by connect function.
  void disconnect(int id) const
  {
    m_slots.erase(id);
  }

  // Disconnects all previously connected functions.
  void disconnect_all() const
  {
    m_slots.clear();
  }

  //! Calls all connected functions.
  void emit(Args... p)
  {
    for (auto it : m_slots)
      it.second(p...);
  }

private:
  mutable std::map<int, std::function<void(Args...)>> m_slots;
  mutable int m_current_id;
};

#endif /* SIGNAL_H */

具有测试:

  signal<> s0;
  int id0 = -1;
  UTEST_CHECK(id0 != 1);
  id0 = s0.connect_member(this, &signal_utest::test0);
  UTEST_CHECK(id0 == 1);
  UTEST_CHECK(get_test0() == 0);
  s0.emit();
  UTEST_CHECK(get_test0() == 1);

  signal<int> s1;
  UTEST_CHECK(s1.connect_member(this, &signal_utest::test1) == 1);
  UTEST_CHECK(test1() == 0);
  s1.emit(1);
  UTEST_CHECK(test1() == 1);

  signal<int, int> s2;
  UTEST_CHECK(s2.connect_member(this, &signal_utest::test2) == 1);
  UTEST_CHECK(test2() == 0);
  s2.emit(1, 1);
  UTEST_CHECK(test2() == 2);