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
    Z
    :从decorator基类继承并动态扩展核心类的功能
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的列表而不是成员方法的指针列表呢?@frank
regDecorator
似乎是个好主意,但我必须检查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
  }
};