我正在尝试一个允许自动观察者/观察功能的模板设计。我有两个嫌疑人:
- 静态继承没有按照我在
Observing::notify()
上期望的方式发生。 - 我尝试绑定到模板
TYPE
类中的enum class
的TYPE::Status
模板化参数。
#include <iostream>
#include <set>
// Observer base class
template <class TYPE>
struct Observing
{
template <class STATUS = TYPE::Status>
void notify(STATUS status);
protected:
// Constructed only through inheritance
Observing() { TYPE::subscribe(this); }
~Observing() { TYPE::unsubscribe(this); }
};
// Class being observed
template <class TYPE>
struct Observable
{
static void subscribe (Observing<TYPE>* obs) { observers.insert(obs); }
static void unsubscribe (Observing<TYPE>* obs) { observers.erase(obs); }
static std::set<Observing<TYPE>*> observers;
};
// Static definition of observable object's observers container
template <class TYPE>
std::set<Observing<TYPE>*> Observable<TYPE>::observers;
// Implementation of an observable service
struct Service : Observable<Service>
{
enum class Status { Up, Down };
void broadcast(Status status)
{
for (Observing<Service>* obs : observers)
obs->notify(status); // <--- unable to link `notify()`
}
};
struct Process: Observing<Service>
{
void notify(Service::Status status)
{
switch (status)
{
case Service::Status::Up: std::cout << "Service is UPn"; break;
case Service::Status::Down: std::cout << "Service is DOWNn"; break;
}
}
};
int main()
{
Service service;
Process worker;
service.broadcast(Service::Status::Up);
}
我想也许Process::notify()
的定义为时已晚,但我试图将声明放在Service
上面,将定义放在下面,但随后我不得不向前声明Service
并且找不到声明Service::Status
的方法。
也许我的方法太复杂了...
在我的理解中,你想要实现的东西是行不通的。在此代码中,编译器只能在结构Observing
中找到一个没有主体的notify
函数。所以链接器稍后会抱怨它。
for (Observing<Service>* obs : observers)
obs->notify(status); // <--- unable to link `notify()`
让我们尝试帮助编译器选择正确的函数。由于我们处于编译时,因此可以使用static_cast。让我们试试:
static_cast<To what?>(obj)->notify(status);
这个问题的答案(static_cast什么)只能在运行时获得 - 这导致我们进入动态多态性。
因此,您必须尝试另一种解决方案:要么使用运行时多态性,要么更改类的体系结构。
观察者模式的要点是主体不知道观察者的静态类型。您将需要virtual
.这意味着notify
不能成为模板,您需要修复Observable
的哪个成员表示要notify
的参数。
template <class TYPE>
struct Observing
{
using Status = typename TYPE::Status;
virtual void notify(Status status);
// ...
};
为了安全起见,请在覆盖它的位置添加override
struct Process: Observing<Service>
{
void notify(Status status) override;
};