C++ Decorator模式:我如何从核心类调用Decorator包装器的一些成员
我正在按照中的示例实现装饰器模式:C++ Decorator模式:我如何从核心类调用Decorator包装器的一些成员,c++,callback,decorator,C++,Callback,Decorator,我正在按照中的示例实现装饰器模式: ClassI:是接口类,对核心类和装饰器基类都是通用的 ClassA:是核心类 ClassD:是装饰器基类 类X,Y,Z:从decorator基类继承并动态扩展核心类的功能 类A(A::endTraining())中有一个方法,该方法在计时器变量末尾触发(也存在于类A)。此方法需要调用X、Y和Z类的某些成员。 可能吗?这是个好习惯吗?怎么做 例如,在类a中创建注册指向-XYZ::endTraining的指针的机制是否正确 (仅显示相关位) typedef
- Class
:是接口类,对核心类和装饰器基类都是通用的I
- Class
:是核心类A
- Class
:是装饰器基类D
- 类
,X
,Y
:从decorator基类继承并动态扩展核心类的功能Z
A
(A::endTraining()
)中有一个方法,该方法在计时器变量末尾触发(也存在于类A
)。此方法需要调用X
、Y
和Z
类的某些成员。可能吗?这是个好习惯吗?怎么做 例如,在类
a
中创建注册指向-XYZ::endTraining
的指针的机制是否正确
(仅显示相关位)
typedef void(D::*pCallback_fn)(void);
第一类
{
公众:
虚拟void endTraining()=0;
虚拟void regTrainingCallbacks(pccallback_fn ptrFn)=0;
};
A类:公共I类{
公众:
void endTraining(){
//做事
//然后在D(及其衍生物)中做一些事情
//通过遍历fnList
}
void regTrainingCallbacks(pccallback\u fn ptrFn)
{
fnList.推回(ptrFn);
}
私人:
std::列表fnList;
};
D类:公共I类{
公众:
D(I*内部){
m_wrappee=内部;
}
void regTrainingCallbacks(pccallback\u fn ptrFn)
{
m_wrappee->regTrainingCallbacks(ptrFn);
}
私人:
我是拉佩;
};
类X/*,Y,Z*/:公共D{
公众:
X(I*核心):D(核心)
{
D::regTrainingCallbacks(this->*endTraining())//
}
私人:
void endTraining(){
//当A::endTraining()通过D调用时执行操作
}
};
可以做些什么呢?解决原始设计中的一个错误,即“培训师”(注册培训回调的实体)本身必须是回调(是否有任何理由通知者-前一个类
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
}
};
类EndTrainingListener
{
公众:
虚拟~EndTrainingListener(){}
虚拟void endTraining()=0;
};
课堂教学过程
{
公众:
虚拟~ITrainingProcess(){}
虚拟void regTrainingCallbacks(EndTrainingListener*callback)=0;
};
班级维护培训流程:公共IT培训流程{
公众:
虚拟~maintainingprocess(){
//销毁培训期间使用的其他资源
}
虚拟无效regTrainingCallbacks(EndTrainingListener*回调){
此->侦听器。向后推(回调);
}
无效列车(){
//训练
// ...
//在培训结束时执行我的具体操作
// ...
//通过通知所有侦听器完成
此->atEndTraining();
}
受保护的:
void atEndTraining(){
用于(自动l:此->侦听器){
l->endTraining();
}
}
std::列出侦听器;
};
类X/*Y,Z*/:公共端训练侦听器{
公众:
虚拟~X();
虚拟虚拟训练(){
//做特定的事情
}
};
您还需要一个对象D
来调用在fnList
中注册的方法。事实上,您可以通过添加另一个虚拟方法virtual void regDecorator(D*decorator)
在类A
中注册所有decorator,该方法将由D
的构造函数调用。此方法将通过在fnList
之外的字段中注册来实现。然后,A::endTraining
可以调用所有装饰器上的fnList
的所有回调方法。如果您只想通知X
decorators或注册回调的X
,可能会有所不同。为什么不使用std::function
s的列表而不是成员方法的指针列表呢?@frankregDecorator
似乎是个好主意,但我必须检查XYZ是否都有“endTraining()`方法。我正在查找有关如何执行此操作的信息,但找不到任何方法。它是否像测试null
一样简单?@skypjack如果我最终没有通过decorator本身,那么我将:)事实上,如果对regDecorator
的调用在X
中,则只能注册具有endTraining
方法的decorator>skypjack的解决方案是,因为它可以通过调用类似于D::regTrainingCallBacks(std::bind(&X::endTraining,this))
的东西将回调函数与对象相关联。
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
}
};