我正按照here中的示例实现装饰器模式:
I
:是接口类,对于核心类和装饰器基础类都是通用的A
:是核心班级 D
:是装饰器基础类X
,Y
,Z
:继承自装饰器基础类并动态扩展核心类的功能类A
(A::endTraining()
)中有一个方法,它在计时器变量的末尾触发(同样存在于类A
中)。此方法需要调用X
,Y
和Z
类的某些成员
可能吗?这是好习惯吗?怎么样?
例如,是否正在创建一种机制来在类XYZ::endTraining
中注册指向 - A
的正确方法?
(仅显示相关位)
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
}
};
可以做些什么呢?
答案 0 :(得分:1)
解决原始设计中的一个故障,其中“培训师”#39; (注册训练回调的实体)本身必须是一个回调(是否有任何理由通知 - 前类A
- 必须是回调本身?)。
我改变了班级名称,以证明他们的责任。
MainTrainingProcess
替换了原来的class A
(其实例将被D
- es包裹)和D
本身。
class EndTrainingListener
{
public:
virtual ~EndTrainingListener() { }
virtual void endTraining()=0;
};
class ITrainingProcess
{
public:
virtual ~ITrainingProcess() { }
virtual void regTrainingCallbacks(EndTrainingListener* callback) = 0;
};
class MainTrainingProcess : public ITrainingProcess {
public:
virtual ~MainTrainingProcess() {
// destroy other resources used during training
}
virtual void regTrainingCallbacks(EndTrainingListener* callback) {
this->listeners.push_back(callback);
}
void train() {
// do training stuff
// ...
// do my specific actions at the end of training
// ...
// finish by notifying all listeners
this->atEndTraining();
}
protected:
void atEndTraining() {
for(auto l : this->listeners) {
l->endTraining();
}
}
std::list<EndTrainingListener*> listeners;
};
class X /*Y, Z*/ : public EndTrainingListener {
public:
virtual ~X();
virtual void endTraining() {
// do specific stuff
}
};