我正在设计一个包含可提供对数据库行的访问的类的库。基础数据保存在map中,其中value是union类型。考虑以下基类:
class dbObject
{
protected:
// Get and set property values using generic name for property
union_type GetPropertyValue(string property_name);
void SetPropertyValue(string property_name, union_type value);
// Add mapping from generic property name to column name
void AddPropertyMapping(string property_name, string column_name);
private:
map<property_name, column_name>
map<column_name, union_type>
};
需要继承自dbObject的每个类
这样,呈现给库用户的最终接口类具有适当的访问器并隐藏了底层结构/实现。这里的动机是大多数类共享相同数据的大部分,因此我们希望它们继承访问器和映射设置代码,而不是为每个类单独编写它们。最初我构建的派生类每个都包含一些共享访问器,例如:
class dbDerivedObjectOne : dbObject
{
public:
int GetPropertyOne();
void SetPropertyOne(int value);
string GetPropertyTwo();
void SetPropertyTwo(string value);
};
class dbDerivedObjectTwo : dbDerivedObjectOne
{
public:
double GetPropertyThree();
void SetPropertyThree(double value);
int GetPropertyFour();
void SetPropertyFour(int value);
};
// This is the API class which is presented to the library user
// It has inherited all the necessary accessors and setup code
class dbInterfaceClass : dbDerivedObjectTwo
{
};
正如您所看到的,这个层次结构因此基于叶子/接口类需要的访问器而不是真实的&#34; is-a&#34;你希望在适当的设计中看到的关系。它还会导致一些问题,即某些类需要访问已在父类中公开的某些属性子集,但不希望公开父类中的所有属性,因为其中一些属性是无意义/不存在的对于派生类。
如果没有一个已知的设计模式可供参考,我目前倾向于一个重构,它涉及将派生类分解为单个属性类并使用多重继承来构建接口类。
class dbObjectProperty
{
union_type GetProperty(string property_name)
void SetProperty(string property_name, union_type value)
};
class dbPropertyOne : dbObjectProperty
{
// calls dbObjectProperty::GetProperty() with its property name
// returns the int from the union_type
int GetPropertyOne();
// wraps the int in a union_type
// calls dbObjectProperty::SetProperty() with its property name
int SetPropertyOne(int value);
};
class dbPropertyTwo : dbObjectProperty
{
// calls dbObjectProperty::GetProperty() with its property name
// returns the string from the union_type
string GetPropertyTwo();
// wraps the string in a union_type
// calls dbObjectProperty::SetProperty() with its property name
void SetPropertyTwo(string value);
};
class InterfaceClassOne : dbPropertyOne, dbPropertyTwo
{
// exposes all of the accessors from its parent classes
}
这个解决方案更加精细,允许我将每个接口类构建为一组(可能共享的)属性,每个属性都提供自己的访问器/更改器。但是,实际的实现将涉及从25-30个不同的属性类继承的类,这看起来像一个可怕的多继承设计。而且,这似乎是对继承概念的滥用。接口类并不真正适合&#34;是&#34;与dbObjectProperty的关系,而不是它们实际上是一个集合,我们滥用多重继承,以避免重复访问代码。
问题:
答案 0 :(得分:1)
因此,根据我的理解,您正试图为自己节省一些打字工作。我会建议一个宏观,但我不是那些专家;),所以我甚至不知道它们是否可以工作(尽管可能值得研究)。
我确实找到了另一种解决方案,这是一个简化的例子(vc ++):
template<typename T>
class Property {
private:
std::map<std::string, union_type>& map_ref;
const std::string name;
public:
Property(std::map<std::string, union_type>& my_map, std::string&& name) : map_ref(my_map), name(name) {}
T Get() const {
return static_cast<T>(map_ref[name]);
}
void Set(T new_value) const {
map_ref[name] = static_cast<union_type>(new_value);
}
};
class MyObject {
private:
std::map<std::string, union_type> my_map;
public:
const Property<int> my_int{ my_map, "my_int" };
};
我不清楚你是如何从union_type
转到别人的,所以我在这里用静态演员表示。
这样做的缺点是获取和设置需要更多的努力。 my_object.my_int.Get()
。不过,它应该可以节省一些工作,而不必输入每个吸气剂和制定者。
这样做的好处是,您仍然可以使用实际的属性名称进行访问,而不仅仅是PropertyOne,PropertyTwo等。(其中,imho,很不错......)