c++ - 多个序列化目标/格式(不是版本)的设计方法

标签 c++

无论是作为成员,可能是静态的,单独的命名空间,通过友元,甚至通过重载,或者任何其他 C++ 语言特性......

当面临支持多种/不同格式的问题时,可能是协议(protocol)或您的类型的任何其他类型的目标,最灵活和可维护的方法是什么?

是否有任何约定或明确的赢家?

简要说明为什么特定方法有帮助会很好。

谢谢。

[像 ProtoBufs 这样的建议不应该为了投票而削减它,不管那个特定的 impl 可能多么灵活:)]

最佳答案

通读了已经发布的回复,我只能同意中间层方法。

基本上,在您的原始问题中,您有 2 个不同的层次结构:

  • n 类
  • m 协议(protocol)

天真的使用 Visitor模式(尽我所能)只会导致 n*m方法......这真的很恶心,是通往维护噩梦的门户。我想你已经注意到了,否则你不会问!

“明显”的目标方法是寻找 n+m解决方案,其中 2 个层次结构明确分开。这当然引入了中间层。

因此想法是ObjectA -> MiddleTier -> Protocol1 .

基本上,这就是 Protocol Buffers 所做的,尽管它们的问题是不同的(通过协议(protocol)从一种语言到另一种语言)。

计算出中间层可能相当困难:

  • 性能问题:“翻译”阶段增加了一些开销,这里是从 1 到 2,虽然这可以缓解,但您必须努力解决。
  • 兼容性问题:例如,某些协议(protocol)不支持递归(xml 或 json 支持,edifact 不支持),因此您可能不得不采用最不常见的方法或找出模拟此类行为的方法。

就个人而言,我会选择将 JSON 语言(非常简单)“重新实现”到 C++ 层次结构中:

  • 内部
  • 字符串
  • 列出
  • 字典

应用Composite模式来组合它们。


当然,这只是第一步。现在您有了框架,但还没有消息。

您应该能够根据原语指定一条消息(现在就真正考虑版本控制,一旦您需要另一个版本就太晚了)。请注意,这两种方法都是有效的:

  • 代码内规范:您的消息由原语/其他消息组成
  • 使用代码生成脚本:这似乎有点过分了,但是......为了完成,我想我会提到它,因为我不知道你真正需要多少消息:)

关于实现:

Herb Sutter 和 Andrei Alexandrescu 在他们的 C++ Coding Standards 中说

Prefer non-member non-friend methods

这非常适用于 MiddleTier -> Protocol步骤 > 创建一个 Protocol1类然后你可以有:

Protocol1 myProtocol;
myProtocol << myMiddleTierMessage;

operator<<的使用因为这种手术是众所周知且非常普遍的。此外,它为您提供了一种非常灵活的方法:并非所有消息都需要实现所有协议(protocol)。

缺点是它不适用于输出协议(protocol)的动态选择。在这种情况下,您可能希望使用更灵活的方法。在尝试了各种解决方案之后,我决定使用带有编译时注册的策略模式。

我的想法是,我使用一个包含许多 Functor 对象的 Singleton。每个对象(在本例中)都针对特定的 Message - Protocol 进行了注册组合。这在这种情况下效果很好。


最后,对于 BOM -> MiddleTier步骤,我会说 Message 的特定实例应该知道如何构建自身,并且应该需要必要的对象作为其构造函数的一部分。

这当然只有在您的消息非常简单并且只能由很少的对象组合构建时才有效。如果没有,您可能需要一个相对空的构造函数和各种 setter,但第一种方法通常就足够了。


把它们放在一起。

// 1 - Your BOM
class Foo {};
class Bar {};

// 2 - Message class: GetUp
class GetUp
{
  typedef enum {} State;
  State m_state;
};

// 3 - Protocl class: SuperProt
class SuperProt: public Protocol
{
};

// 4 - GetUp to SuperProt serializer
class GetUp2SuperProt: public Serializer
{
};

// 5 - Let's use it
Foo foo;
Bar bar;

SuperProt sp;
GetUp getUp = GetUp(foo,bar);

MyMessage2ProtBase.serialize(sp, getUp); // use GetUp2SuperProt inside

关于c++ - 多个序列化目标/格式(不是版本)的设计方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1711426/

相关文章:

c++ - 通过引用传递一个指向 long 的指针

c++ - 获取行验证

c++ - vector::push_back() 是否在进行浅拷贝以及如何解决这个问题

c++ - CMAKE Compile_Flag

c++ - 在 C++ 中散列字典

c++ - 错误: reference to ‘int64’ is ambiguous Compiling problem opencv + dlib in QT

c++ - 更改给定 STL 容器的 value_type

C++ 二进制搜索一个类

c++ - 对共享内存的原子访问

C++ 在 while 循环后 map 的大小仍然是 1