gpt4 book ai didi

c++ - 多态数据转换/转换设计模式

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:17:58 24 4
gpt4 key购买 nike

问题如下:

考虑下面的类

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中提供一个接口(interface)如下

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&);

因此,我们以“较少面向对象”的解决方案为代价避免了派生类的污染,并可能以大量执行这些翻译操作的能力为代价。

如果我们考虑需要支持除 any_map 之外的许多表示的可能性,这也更有意义,例如

using boost::ptree;
using json_class;
using xml_class;

但再次声明,它不是多态的。

我读过的大多数“翻译”设计模式都与接口(interface)有关,但我还没有找到一个正式解决多态性上下文中数据翻译/转换的模式。

我正在寻找对正式解决此问题的设计模式的引用、关于如何继续实现的建议和/或指出我的方法中的明显缺陷。

最佳答案

根据评论中的要求,下面的代码说明了我所描述的访问者模式的使用。只需为输入、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++ - 多态数据转换/转换设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30752404/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com