我正在写一个DAL / ORM库。该库主要从GUI访问,但也可以从一些“业务级”应用程序访问。我还处在这个库的设计阶段,并且我不确定如何很好地解决以下问题。
在我目前的设计中,我有一个类,我们暂时称它为List
,它有另一个类的容器Properties
。属性有两种类型(A和B),大多数功能相同,但它们的一些功能不同。此外,Properties
两种风格都存储了价值。值可以是不同的数据类型,包括但不限于POD。每个List
只能包含一次Property
,Properties
只能通过“名称”标识,即字符串。
我现在希望能够做到以下所有事情:
Properties
中的所有List
进行迭代,并调用Property
种口味支持的方法。Property
的实例时,以类型安全的方式访问其值dynamic_cast
或类似的构造所以,显然纯粹的多态性不能在这里做到。我已经使用奇怪的重复模板模式和两个类层次结构的组合进行了一些实验 - 一个用于Properties
,另一个用于它们的值(下面的示例代码) 。但是,到目前为止,我没有成功地完成满足我所有要求的设计。
基本设计(即存在哪些类,它们如何组织等)不是固定的,可以很容易地改变。我仍处于该项目的设计阶段,因此只存在测试代码。但是,基本思想必须如上所述(即List
有Properties
,而values
又有class PropertyValue {
public:
virtual std::string GetAsString() const = 0;
bool IsReadOnly() const { return m_isReadOnly; }
void IsReadOnly(const bool val) { m_isReadOnly = val; }
protected:
PropertyValue(PropertyValue & other) : m_isReadOnly(other.m_isReadOnly)
{};
PropertyValue(bool readOnly) : m_isReadOnly(readOnly)
{};
private:
bool m_isReadOnly;
};
class StringValue : public PropertyValue {
private:
typedef std::string inner_type;
public:
StringValue(const inner_type & value, bool readOnly) : PropertyValue(readOnly)
, m_value(value)
{};
StringValue(StringValue & other) : PropertyValue(other.IsReadOnly())
, m_value(other.m_value)
{};
std::string GetAsString() const { return m_value; };
inner_type GetValue() const { return m_value; };
void SetValue(const inner_type & value) { m_value = value; };
unsigned int GetMaxLenght() const { return m_maxLength; };
private:
inner_type m_value;
unsigned int m_maxLength;
};
class IntValue : public PropertyValue {
private:
typedef int inner_type;
public:
IntValue(const inner_type & value, bool readOnly) : PropertyValue(readOnly)
, m_value(value)
{};
IntValue(IntValue & other) : PropertyValue(other.IsReadOnly())
, m_value(other.m_value)
{};
std::string GetAsString() const { char tmp[((CHAR_BIT * sizeof(int)) / 3 + 1)]; return itoa(m_value, tmp, 10); };
inner_type GetValue() const { return m_value; };
void SetValue(const inner_type & value) { m_value = value; };
int GetMinValue() const { return m_minValue; };
int GetMaxValue() const { return m_maxValue; };
private:
inner_type m_value;
int m_minValue;
int m_maxValue;
};
class Property {
public:
Property(std::auto_ptr<PropertyValue> value, bool visible)
{
m_value = value;
m_isVisible = visible;
}
bool IsVisible() const { return m_isVisible; }
void IsVisible(const bool val) { m_isVisible = val; }
std::string GetValueAsString() const { return m_value->GetAsString(); };
const PropertyValue & getValue() const { return (*m_value.get()); }
private:
std::auto_ptr<PropertyValue> m_value;
bool m_isVisible;
};
class PropertyFlavorA : public Property {
public:
PropertyFlavorA(std::auto_ptr<PropertyValue> value, bool visible) : Property(value, visible)
{
value->IsReadOnly(true);
};
};
class PropertyFlavorB : public Property {
public:
PropertyFlavorB(std::auto_ptr<PropertyValue> value, bool visible) : Property(value, visible) {};
};
。
我的问题或原创想法,想法等的任何解决方案都受到高度赞赏。
层次结构实现的示例代码。显然,我不能在这里以类型安全的方式访问属性的值。
{{1}}
答案 0 :(得分:1)
您似乎已回答了自己的问题......
对
Properties
中的所有List
进行迭代,并调用Property
种口味支持的方法。
这是polymorphism。
Properties
的两种口味都有一个基类,它有一个虚拟函数,你的A和B Property
类覆盖它们。然后,您可以从存储在List
。
答案 1 :(得分:0)
我最终决定在我的List
课程中使用boost::variant的向量。我的Property
类现在是一个模板类,其中模板参数使用ValueType
类的子类进行实例化。 Properties
的不同风格来自Property
类。
现在看来这种方法符合我的所有初始要求:
Properties
中的所有List
进行迭代,并使用std::for_each和boost::apply_visitor调用Property
种口味支持的方法✓Property
的实例时,如果我的Property
基类可以访问其ValueType
成员,则可以以类型安全的方式访问其值。 ✓对这种方法的任何评论仍然受到赞赏。