我经常发现自己陷入困境,在哪里为一个班级编写序列化代码,并且想知道别人对这个主题的看法是什么。
沼泽标准序列化是没有道理的。只需装饰有问题的课程。
对于通过各种协议或不同格式进行序列化并且需要对流程进行一些思考/优化而不是盲目地序列化装饰属性的类,我的问题更多。
我经常觉得将所有代码与其自己的类中的一种格式保持一致更为清晰。它还允许您通过添加新类来添加更多格式。 例如
class MyClass
{
}
Class JSONWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class BinaryWriter
{
public void Save(MyClass o);
public MyClass Load();
}
Class DataBaseSerialiser
{
public void Save(MyClass o);
public MyClass Load();
}
//etc
然而,这通常意味着MyClass必须向外界公开更多内部,以便其他类有效地序列化。这感觉不对,反对封装。有办法解决它。例如,在C ++中,您可以将序列化器作为朋友,或者在C#中,您可以将某些成员公开为显式接口,但它仍然感觉不太好。
另一个选择当然是让MyClass知道如何将自己序列化为各种格式:
class MyClass
{
public void LoadFromJSON(Stream stream);
public void LoadFromBinary(Stream stream);
public void SaveToJSON(Stream stream);
public void SaveToBinary(Stream stream);
//etc
}
这感觉更加封装和正确,但它将格式与对象相结合。如果由于MyClass不知道的某些上下文,某些外部类知道如何更有效地序列化怎么办? (也许一大堆MyClass对象引用相同的内部对象,因此外部序列化器可以通过仅序列化一次来优化)。此外,如果您需要新格式,则必须在所有对象中添加支持,而不是仅仅编写新类。
有什么想法?就个人而言,我根据项目的确切需要使用了这两种方法,但我只是想知道是否有人有某种强烈的理由支持或反对某种特定的方法?
答案 0 :(得分:2)
最灵活的模式是保持对象的轻量级,并为特定类型的序列化使用单独的类。
如果您需要添加另外3种类型的数据序列化,请想象一下这种情况。你的课程会因为他们不关心的代码而变得臃肿。 “物体不应该知道它们是如何消耗的”
答案 1 :(得分:2)
我想这实际上取决于使用序列化的上下文以及使用它的系统的局限性。例如,由于Silverlight反射限制,需要公开一些类属性才能使序列化器工作。另外一个,WCF序列化程序要求您特别了解可能的运行时类型。
除了你所指出的,将序列化逻辑放入类中会违反SRP。为什么一个班级需要知道如何将自己“翻译”成另一种格式?
在不同情况下需要不同的解决方案,但我主要看到分离的序列化程序类正在完成这项工作。当然需要暴露类内部的某些部分,但在某些情况下你还是必须这样做。