我刚开始学习设计模式,而且我对一些应该是简单的概念有困难。其中一些模式的概念很有意义,但我在如何用C ++实现它们方面苦苦挣扎。
让我说我正在处理一个实现观察者问题的问题。让我们假设只有一个观察者。这留下了两个需要沟通的对象:主体和观察者。
从概念上讲,这种模式试图做的事情很容易理解。然而,我被这样的问题所困扰:他们在哪里反对生活?他们都必须住在某个容器内吗?他们如何实际提出彼此的请求?
关于最后一个问题,是否每个对象都必须有一个引用另一个对象的数据成员?如同,主题必须包含指向观察者的指针,并且观察者是否必须包含指向主题的指针?
离开观察者。如果我有任何两个相互依赖的对象(单向或双向),是否每个对象都有一个指向其各自对象的指针?
谢谢,
答案 0 :(得分:1)
可用于使对象进行通信的另一种方法是通过中间Queue对象,或套接字或其他类型的共享内存,因此并不总是需要存储指向另一个对象的指针。事实上,为了改善解耦和编写通用代码,通常最好使用事件队列或信号(参见QT库的设计)。
不要认为存储指针是错误的:它通常是一个很好的解决方案,并避免过度工程,这是昂贵的(在金钱,时间和其他计算资源方面)。
答案 1 :(得分:1)
观察者模式的典型高级运行时多态实现具有 observable 对象添加数据成员,例如std::vector<Observer*> observers_;
,并且当感兴趣的事件发生时,observable的成员函数迭代observers_
通过Observer*
调用某个函数。 Observer
s不一定需要保持对observable
对象的指针/引用,但如果它有用,它们可能会这样做,或者来自可观察对象的回调可能会传递this
。 }指针或对*this
的引用作为参数。更简单的可观察量可能只支持一个Observer*
而不是其容器。
对于较低级别/性能关键的代码 - 由于您知道编译时涉及的类型,这样做是可行的 - 您可能更喜欢在编译时规定一个或多个观察者 - 可能作为模板参数。这可以允许调度内联和优化,消除死代码,以避免调用不执行任何操作的观察者等。
他们在哪里反对?
对程序中对象的一般功能有意义的任何地方。例如,如果Database_Server_Connection
是可观察的,它可能让程序的其他部分感兴趣知道何时异步建立连接,何时连接被丢弃,何时异步请求完成,何时数据库连接被程序代码关闭,当数据库可观察对象的析构函数运行时。观察者可以是程序中的任何其他位置 - 它们可能是某个函数范围内的本地对象,可能是另一个线程中的本地对象,或者它们可能位于静态或动态分配容器中的智能指针中或由其管理。
他们都必须住在某个容器内吗?
不 - 如上所述。
他们如何实际提出彼此的请求?
首先,添加观察者的代码需要访问可观察对象,并且通常调用observable.add_observer(this);
之类的东西来注册自己,注意在析构函数中调用observable.remove_observer(this);
,这样observable就不会意外地尝试调用进入一个已被“破坏”的物体。然后使用由add_observer
隐藏的指针进行回调。如上所述,回调可以作为参数传递指针或对observable的引用,观察者可能先前将指针或引用隐藏起来,或者如果他们需要的所有信息都传递给回调,他们甚至可能不需要一个不需要变异(在非const
函数上调用)observable。
离开观察者。如果我有任何两个相互依赖的对象(单向或双向),是否每个对象都有一个指向其各自对象的指针?
这通常是最简单的,但有时可能会使用某些其他通信机制,例如队列或套接字,在这种情况下,通信方需要某种方式的指针/引用/句柄/ id用于该通信机制,而不是指向彼此的指针