装饰器模式:如何从核心类中调用(回调)装饰器包装器的一些成员

Decorator pattern: how can I call(back) some members of decorator wrappers from the core class

本文关键字:回调 包装 成员 模式 核心 调用      更新时间:2023-10-16

我正在按照下面的示例实现一个装饰器模式:

  • I:是接口类,与核心类和装饰器基类共同使用。
  • A类:为核心类
  • D:为装饰基
  • X, Y, Z:继承装饰器基类,动态扩展核心类的功能

A (A::endTraining())中有一个方法,它在计时器变量(也存在于类A中)的末尾触发。这个方法需要调用XYZ类中的某个成员。
这可能吗?这是好的练习吗?如何?

例如,创建一种机制来注册指向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
    }
};

可以做什么来代替?

解决原始设计中的一个错误,其中'trainer'(注册培训回调的实体)本身必须是回调(是否有任何理由通知器-前类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
  }
};