装饰器模式:如何从核心类

时间:2016-08-28 12:40:42

标签: c++ callback decorator

我正按照here中的示例实现装饰器模式:

  • I:是接口类,对于核心类和装饰器基础类都是通用的
  • 班级A:是核心班级
  • D:是装饰器基础
  • XYZ:继承自装饰器基础类并动态扩展核心类的功能

AA::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
    }
};

可以做些什么呢?

1 个答案:

答案 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
  }
};