【发布时间】:2017-01-04 14:33:51
【问题描述】:
我正在按照here 中的示例实现装饰器模式:
- Class
I:是接口类,core类和decorator base类都通用 - 类
A:是核心类 - 类
D:是装饰器基类 - 类
X、Y、Z:继承自装饰器基类并动态扩展核心类的功能
A (A::endTraining()) 类中有一种方法,它在计时器变量结束时触发(也存在于A 类中)。此方法需要调用X、Y 和Z 类的某个成员。
可能吗?这是好习惯吗?怎么样?
例如,创建一种机制来在A 类中注册 pointers-to-XYZ::endTraining 是一种正确的方法吗?
(仅显示相关位)
typedef void (D::*pCallback_fn)(void);
class I
{
public:
virtual void endTraining() = 0;
virtual void regTrainingCallbacks(pCallback_fn ptrFn) = 0;
};
class A: public I {
public:
void endTraining() {
//do stuff
//then do stuff in D (and its derivatives)
// by iterating through fnList
}
void regTrainingCallbacks(pCallback_fn ptrFn)
{
fnList.push_back( ptrFn );
}
private:
std::list<pCallback_fn> fnList;
};
class D: public I {
public:
D(I *inner) {
m_wrappee = inner;
}
void regTrainingCallbacks(pCallback_fn ptrFn)
{
m_wrappee->regTrainingCallbacks(ptrFn);
}
private:
I *m_wrappee;
};
class X /*,Y,Z*/ : public D {
public:
X(I *core): D(core)
{
D::regTrainingCallbacks( this->*endTraining() ); //
}
private:
void endTraining(){
//do stuff when called by A::endTraining() through D
}
};
可以做些什么呢?
【问题讨论】:
-
你还需要一个对象
D来调用fnList中注册的方法。实际上,您可以通过添加另一个将由D的构造函数调用的虚拟方法virtual void regDecorator(D* decorator)在类A中注册所有装饰器。该方法将在A中通过在fnList之外的字段中注册来实现。那么A::endTraining就可以在所有装饰器上调用fnList的所有回调方法。如果您只想通知X装饰器或已注册回调的X,可能会有所不同。 -
为什么不使用
std::functions 列表而不是指向成员方法的指针列表? -
@Franck
regDecorator似乎是个好主意,但是我必须检查 XYZ 是否都有“endTraining()` 方法。我正在寻找有关如何做到这一点的信息,但找不到任何. 是不是像测试null一样简单? -
@skypjack 如果我最终没有通过装饰器本身,那么我会:)
-
事实上,如果
regDecorator的调用在X构造函数中,你只能注册具有endTraining方法的装饰器。 skypjack的解决方案是因为它可以通过调用D::regTrainingCallBacks(std::bind(&X::endTraining, this))之类的方式将回调函数关联到对象。