【问题标题】:Choosing method implementation at runtime在运行时选择方法实现
【发布时间】:2013-05-17 10:17:31
【问题描述】:

我想通过选择调用给定集合的方法来配置对象在运行时的行为。考虑这个简单的例子:

class Parameter;

class Conf;

class Obj {
public:
    Obj( const Conf &t ): t_( t ) {}
    void f( Parameter *d );
    void f1( Parameter *d );
    void f2( Parameter *d );
    typedef void ( Obj::*Fn )( Parameter *d );
private:
    const Conf &t_;
};

class Conf {
public:
    Obj::Fn f;
};

void Obj::f( Parameter *d ) {
    ( this->*t_.f )( d );
}

通过为给定的Conf 对象更改Conf::f,所有使用此配置的Obj 对象的行为都会发生更改。

第一个问题:这是否类似于某种设计模式(好吧,它是一种方法-指针-策略-事物......)?如果是这样,我应该考虑重新设计吗?

第二个问题:我想通过使用不同的参数类来使其更加灵活。我已经通过使Parameter 成为基类并在fN 方法中进行类型转换来做到这一点,但这看起来不像是最终解决方案。有什么建议吗?

【问题讨论】:

  • 策略模式可能在这里起作用。
  • 关于您的参数问题,将 Obj 或 Parameter 设为模板类型?
  • 考虑使用 std::function 代替方法指针。
  • @verbose-mode 方法f1()f2() 修改对象的内部状态。策略模式适用于这种情况吗?
  • @Spook 你的意思是用boost::function< void ( Obj*, Parameter* ) > f; 的声明替换typedef(我这里还是C++03)?有什么好处?

标签: c++ design-patterns


【解决方案1】:

这让我想起了State pattern,考虑到当状态改变时,会在不同的对象上调用一个方法。如果您查看 wikipedia 链接的 Java 示例,StateContext 对象具有 myState 属性,该属性将更改为不同的 State 对象以进行状态更改。

你可以做类似的事情,你的 Obj 类将有一个指向一个对象的指针/引用,该对象实现了它实现的接口中指定的方法。然后可以通过内部逻辑或通过外部设置将内部指针/引用更改为指向不同的对象,然后调用的方法将不同。

这是一个简单的例子:

class Action
{
    virtual void action() = 0;
}

class Action1 : public Action
{
    virtual void action() { /* do something useful here */ }
};

class Action2 : public Action
{
    virtual void action() { /* do something different here */ }
}

class Obj
{
public:
    setAction(Action *a) {a_ = a;}
    void action() {if(a_) a_->action();}
private:
    Action *a_;
};

{
    Action1 a1;
    Action2 a2;
    Obj o;
    o.setAction(&a1);
    o.action();

    o.setAction(&a2);
    o.action();
}

正如 cmets 中提到的,这也与策略模式非常相似。

【讨论】:

  • 这比将函数对象(带有重载的 operator() )作为模板参数传递有什么优势吗?
  • @nurettin,好问题,我想它归结为模板和继承之间的差异/偏好,这超出了这个问题的范围。
  • 正如我在对该问题的评论中所说,操作应该能够修改对象的内部状态(就像方法一样)。在/* do something useful here */ 中你不能真正做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多