Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将数据传递到';通用';观察者作为参数还是作为单个结构? 我正忙着向一个传统C++应用程序添加一个通用的观察机制(使用Visual Studio 2010,但不使用.NET,所以.NET委托是不可能的)。_C++_Observer Pattern_Observers - Fatal编程技术网

如何将数据传递到';通用';观察者作为参数还是作为单个结构? 我正忙着向一个传统C++应用程序添加一个通用的观察机制(使用Visual Studio 2010,但不使用.NET,所以.NET委托是不可能的)。

如何将数据传递到';通用';观察者作为参数还是作为单个结构? 我正忙着向一个传统C++应用程序添加一个通用的观察机制(使用Visual Studio 2010,但不使用.NET,所以.NET委托是不可能的)。,c++,observer-pattern,observers,C++,Observer Pattern,Observers,在设计中,我希望尽可能将特定于应用程序的部分与通用观察者机制分离 实现观察者的最合乎逻辑的方式似乎是: class IDoThisObserver { public: void handlDoThis(int arg1, int arg2) = 0; }; 对于每种类型的观察者(IDoThisObserver,IDoThatObserver,…),方法(handleDoThis,handleDoThat)的参数都是不同的 以一种通用的方式存储观察者的剩余内容如下:

在设计中,我希望尽可能将特定于应用程序的部分与通用观察者机制分离

实现观察者的最合乎逻辑的方式似乎是:

class IDoThisObserver
   {
   public:
      void handlDoThis(int arg1, int arg2) = 0;
   };
对于每种类型的观察者(IDoThisObserver,IDoThatObserver,…),方法(handleDoThis,handleDoThat)的参数都是不同的

以一种通用的方式存储观察者的剩余内容如下:

template<typename T>
class ObserverContainer
   {
   public:
      void addObserver (T &t) {m_observers.push_back(&t);}
   private:
      std::list<T*> m_observers;
   };
struct DoThisInfo
   {
   DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
   int m_arg1;
   int m_arg2;
   };
template<typename T>
class IObserver
   {
   public:
      void notify(const T &t) = 0;
   };
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
   {
   ...
   };
然后定义一个更通用的观察者,如下所示:

template<typename T>
class ObserverContainer
   {
   public:
      void addObserver (T &t) {m_observers.push_back(&t);}
   private:
      std::list<T*> m_observers;
   };
struct DoThisInfo
   {
   DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
   int m_arg1;
   int m_arg2;
   };
template<typename T>
class IObserver
   {
   public:
      void notify(const T &t) = 0;
   };
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
   {
   ...
   };
模板
类IObserver
{
公众:
无效通知(常数T&T)=0;
};
这些观察者的集合将变成:

template<typename T>
class ObserverContainer
   {
   public:
      void addObserver (IObserver<T> &obs) {m_observers.push_back(&obs);}
   private:
      std::list<IObserver<T>*> m_observers;
   };
模板
类ObserverContainer
{
公众:
void addObserver(IObserver&obs){m_observer.push_back(&obs)}
私人:
标准:列出m_观察员;
};
现在,更多的逻辑可以集中添加到这个observer容器中,包括调用所有观察者。调用的“发起人”只需要创建和填写通知结构

要从多种类型的观察者继承的类需要这样做:

template<typename T>
class ObserverContainer
   {
   public:
      void addObserver (T &t) {m_observers.push_back(&t);}
   private:
      std::list<T*> m_observers;
   };
struct DoThisInfo
   {
   DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
   int m_arg1;
   int m_arg2;
   };
template<typename T>
class IObserver
   {
   public:
      void notify(const T &t) = 0;
   };
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
   {
   ...
   };
class MyObserver:public IObserver,public IObserver
{
...
};
以下哪种方法(具有多个显式参数的观察者或具有一个结构参数的观察者)似乎是最好的?这两种方法都有优点或缺点吗

编辑:我进一步研究了其他方法,插槽/信号方法似乎是另一个不错的选择。插槽/信号是否有我应该知道的重要缺点?

为什么不这样做:

class IObserver {
    // whatever is in common
};

class IDoThisObserver : public IObserver
{
   public:
      void handlDoThis(int arg1, int arg2) = 0;
};

class IDoThatObserver : public IObserver
{
   public:
      void handlDoThat(double arg1) = 0;
};
?

那么你有:

class ObserverContainer
{
   public:
      void addObserver (IObserver* t) {m_observers.push_back(t);}
   private:
      std::list<IObserver*> m_observers;
};
类observer容器
{
公众:
void addObserver(IObserver*t){m_observer.push_back(t)}
私人:
标准:列出m_观察员;
};

带有
struct
参数的设计肯定更好,因为它允许在
ObserverContainer
中编写通用代码。通常,用封装参数的对象替换较长的参数列表是一种很好的设计实践,这是一个很好的回报示例。通过为
notify
方法创建一个更一般的抽象(使用struct,您将
notify
定义为一个获取一大块“数据”的方法,而使用arg list,您将定义一个获取两个数字的方法)您可以编写使用该方法的通用代码,而不必关心传入数据块的确切组成。

我没有正确的语法,所以我只列出声明来说明结构。一个通用的观察者可以期望一个参数,该参数或者是所需参数的特定形式的子类,或者是包含观察者所需的所有基本参数的水平映射的结构。然后,ObserverContainer可以用作,ObserverContainer的每个子类可以是DoThatObserverFactory和DoThisObserverFactory。工厂将构建一个观察器,并为观察器分配一个配置,以告诉它需要哪个参数

class AbstractObserverFactory {...};
class DoThatObserverFactory : AbstractObserverFactory {...};
class DoThisObserverFactory : AbstractObserverFactory {...};
class ObserverParam {...};
class DoThatObserverParam : ObserverParam {...};
class DoThisObserverParam : ObserverParam {...};
class Observer;
class DoThisObserver : public Observer
{
   public:
      void handlDoThis(DoThisObserverParam);
};

我认为你的两种方法都不符合你的要求。然而,使用一个包含数据集的数据载体对所有观察者进行一点修改,其中每个观察者都知道要读取什么,就可以做到这一点。下面的示例代码可能会清除它(注意,我还没有编译)

枚举类型{
通知你,,
通知你
};
结构数据{
虚拟类型getType()=0;
};
结构NotifyThisData:公共数据{
NotifyThisData(int_a,int_b):a(_a),b(_b){
INTA,b;
键入getType(){return NOTIFY_THIS;}
};
结构NotifyThatData:公共数据{
NotifyThatData(std::string _str):str(_str){
std::字符串str;
键入getType(){return NOTIFY_THAT;}
};
结构数据载体{
std::向量m_类型数据;
};
类IObserver{
公众:
虚空句柄(数据载体和数据)=0;
};
类NotifyThis:公共虚拟IObserver{
公众:
虚拟无效句柄(数据载体和数据){
vector::iterator iter=find_if(data.m_TypeData.begin(),data.m_TypeData.end(),bind2nd(functor(),NOTIFY_THIS);
if(iter==data.m_TypeData.end())
返回;
NotifyThisData*d=动态投影(*iter);

std::你有没有研究过增压信号?比重新安装车轮更好

至于参数:调用观察者/插槽在概念上应该与调用普通函数相同。大多数SignalSlot实现允许多个参数,因此使用它。请为不同的观察者类型使用不同的信号,这样就不需要在变量中传递数据

我已经看到了观察者模式/信号槽的两个缺点:
1) 仅通过查看源代码,很难甚至不可能理解程序流程。
2) 具有大量观察者/信号槽的高度动态程序可能会遇到“删除此项”


除此之外,我更喜欢观察者/信号槽,而不是子类化和高耦合。

这只是将通用代码放在IObserver中。我正在寻找一种将通用代码放在ObserverContainer中的方法。这种方法很好,只要不需要迭代观察者并在某些常规情况下调用它们的处理方法-是这样。那将是一场噩梦。问题是
ObserverContainer
无法在没有大量强制转换的情况下调用观察器上的
handle
方法。@bshiels,如果他不知道它们采用什么参数,他怎么能强制转换handle?@Kornel The primary fu