更通用的访客模式

mar*_*jno 9 c++ design-patterns visitors

如果我的问题太长而且技术性很强,我很抱歉,但我认为其他人对此感兴趣非常重要

我正在寻找一种方法来清楚地将一些软件内部结构与它们在c ++中的表示分开

我有一个泛型参数类(稍后存储在容器中),它可以包含boost :: any类的任何类型的值

我有一个这样的基类(大致)(当然还有更多的东西)

class Parameter 
{
public:
    Parameter()
    template typename<T> T GetValue() const { return any_cast<T>( _value ); }
    template typename<T> void SetValue(const T& value) { _value = value; }
    string GetValueAsString() const = 0;
    void SetValueFromString(const string& str) const = 0;
private:
    boost::any _value;
}
Run Code Online (Sandbox Code Playgroud)

派生类有两个级别:第一级定义类型和转换为/来自字符串(例如ParameterInt或ParameterString)第二级定义行为和真实创建者(例如从ParameterInt或ParameterFilename中派生ParameterAnyInt和ParameterLimitedInt)的genericstring)

根据实际类型,我想添加外部函数或根据特定参数类型操作的类,而不向基类添加虚方法,也不做奇怪的转换

例如,我想根据参数类型创建适当的gui控件:

Widget* CreateWidget(const Parameter& p)
Run Code Online (Sandbox Code Playgroud)

当然我无法理解真正的参数类型,除非我使用RTTI或自己实现(使用枚举和开关案例),但这不是正确的OOP设计解决方案,你知道.

经典的解决方案是访客设计模式http://en.wikipedia.org/wiki/Visitor_pattern

这种模式的问题是我必须事先知道将实现哪些派生类型,所以(将维基百科和我的代码中写的内容放在一起)我们将有以下几种:

struct Visitor 
{
  virtual void visit(ParameterLimitedInt& wheel) = 0;
  virtual void visit(ParameterAnyInt& engine) = 0;
  virtual void visit(ParameterFilename& body) = 0;
};
Run Code Online (Sandbox Code Playgroud)

是否有任何解决方案可以以任何其他方式获得此行为,而无需事先知道所有具体类型并且无需派生原始访问者?


编辑: Pizza博士的解决方案似乎与我的想法最接近,但问题仍然是相同的,并且该方法实际上依赖于dynamic_cast,我试图避免作为一种(即使是弱的)RTTI方法

也许最好不要引用访问者模式并清理我们的想法来考虑某些解决方案.目的只是具有以下功能:

Widget* CreateWidget(const Parameter& p)
Run Code Online (Sandbox Code Playgroud)

每个"具体"参数的行为都不同,而不会丢失其类型的信息

gra*_*eds 0

如果我理解正确的话......

我们有一个可以使用不同硬件选项的对象。为了方便这一点,我们使用了 Device 的抽象接口。设备有很多会在某些事件上触发的函数。用途是相同的,但设备的各种实现要么具有完整的功能,要么立即返回。为了让生活变得更加轻松,这些函数是无效的,并在出现问题时抛出异常。