多态数据转换/转换设计模式
Polymorphic Data Translation/Conversion Design Pattern
问题如下:
考虑以下类
class data : public base_data
{
public:
int a;
std::string b;
double c;
... // many other members
};
假设公开此类的数据成员是完全有意义的。
现在考虑有许多这样的类,每个类都有不同的成员,也许都派生自同一个基类"base_data"。
现在,这些类需要从其他任意数据表示中导出、导入、构造、"设置"和"获取"。
例如:
using any_map = boost::unordered_map < std::string, boost::any > ;
就是这样一种表示。
此外,所有这些操作都需要大量完成,即通过 base_data* 对象的集合进行多态性操作。
此问题的一种解决方案是提供base_data
接口,如下所示class base_data
{
public:
virtual void set(const any_map&) = 0;
virtual any_map get() const = 0;
};
每个派生类都知道其成员,因此它知道如何进行转换。 此外,派生类可以提供窗体的构造函数
data(const any_map&) {...}
允许轻松定义抽象工厂模式。
这个问题的另一个解决方案是在每个派生类型的某个命名空间下提供静态翻译函数,例如
static data convert(const any_map&);
static any_map convert(const data&);
因此,我们避免了派生类的污染,代价是"更少的 OO"解决方案,并且可能具有大规模执行这些转换操作的能力。
如果我们考虑需要支持除any_map以外的许多表示的可能性,这也更有意义,例如
using boost::ptree;
using json_class;
using xml_class;
但再一次,它不是多态的。
我读过的大多数"翻译"设计模式都涉及接口,但我还没有找到一种在多态性上下文中正式解决数据转换/转换
的模式。我正在寻找对正式解决此问题的设计模式的参考,有关如何继续实施的建议和/或指出我的方法中的明显缺陷。
按照注释中的要求,下面的代码说明了我所描述的访问者模式的使用。 只需添加额外的访问者输入,JSON,CSV或您需要的任何格式。 请注意,不需要修改访问者来处理不同的记录结构 - 下面的实现只需要知道如何通过虚拟调度处理涉及的不同字段类型。 所有这些最终都类似于 boost 序列化库,我建议也看看它。
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
struct Visitor
{
typedef const char* Identifier; // or string...
Visitor(std::ostream& os) : os_(os) { }
virtual Visitor& pre(Identifier) { return *this; }
template <typename T> Visitor& operator()(Identifier id, const T& t)
{
std::ostringstream oss;
oss << t;
return operator()(id, oss.str());
}
virtual Visitor& operator()(Identifier, double) = 0;
virtual Visitor& operator()(Identifier, const std::string&) = 0;
virtual Visitor& post() { return *this; }
std::ostream& os_;
};
struct Visitor__XML_Out : Visitor
{
using Visitor::Visitor;
Visitor& pre(Identifier i) override
{ os_ << '<' << i << '>'; i_ = i; return *this; }
Visitor& operator()(Identifier f, double x) override
{ return out(f, x); }
Visitor& operator()(Identifier f, const std::string& x) override
{ return out(f, x); }
Visitor& post() override
{ os_ << "</" << i_ << '>'; return *this; }
private:
template <typename T>
Visitor& out(Identifier f, const T& x)
{
os_ << '<' << f << '>' << x << "</" << f << '>';
return *this;
}
Identifier i_;
};
struct Base_Data
{
virtual void visit(Visitor& v) = 0;
};
struct Data : Base_Data
{
int a_;
std::string b_;
double c_;
Data(int a, const std::string& b, double c)
: a_(a), b_(b), c_(c)
{ }
void visit(Visitor& v) override
{
v.pre("Data")("a", a_)("b", b_)("c", c_).post();
}
};
int main()
{
Data d { 42, "hawk", 8.8 };
Visitor__XML_Out xml(std::cout);
d.visit(xml);
std::cout << 'n';
}
输出:
<Data><a>42</a><b>hawk</b><c>8.8</c></Data>
相关文章:
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 资源管理设计模式
- 用于在回调中调用解析器的设计模式
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 在这种情况下我应该使用哪种设计模式
- C++中物体改变识别的设计模式?
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 工厂设计模式优化
- 使用C++模板的数据映射器设计模式
- 为什么以及如何使用原型设计模式
- 具有多个继承共享一个资源的对象 - 寻找良好的设计模式
- 在C++中创建观察器设计模式的好方法
- 现代C++在多大程度上消除了对设计模式的需求?
- 对于存储另一个类所需信息的类,例如其构造,是否有设计模式?
- C++ 设计模式,以避免复制和向下转换
- 要应用于输入的转换链的设计模式
- 设计模式以避免消息传递中的下转换
- 多态数据转换/转换设计模式