我目前正处于C# .NET应用程序的几个模型类的(重新)设计阶段。(模型如MVC中的M)。模型类已经有了大量精心设计的数据、行为和相互关系。我正在将模型从Python重写为C#。
在以前的Python模型中,我想我看到了一个疣。每个模型都知道如何序列化自己,序列化逻辑与任何类的其余行为无关。例如,想象一下:
Image类的.toJPG(String filePath) .fromJPG(String filePath)方法ImageMetaData类,其中包含.toString()和.fromString(String serialized)方法。您可以想象这些序列化方法是如何与类的其他部分不结合的,但是只能保证类知道足够的数据来序列化自己。
发布于 2015-07-04 03:22:35
出于以下几个原因,我通常避免让类知道如何序列化自己。首先,如果您想(反)序列化到/从不同的格式,您现在需要污染模型的额外的逻辑。如果模型是通过接口访问的,那么您也会污染合同。
public class Image
{
public void toJPG(String filePath) { ... }
public Image fromJPG(String filePath) { ... }
}但是,如果您想将其序列化到/从PNG和GIF中序列化呢?现在这个班变成
public class Image
{
public void toJPG(String filePath) { ... }
public Image fromJPG(String filePath) { ... }
public void toPNG(String filePath) { ... }
public Image fromPNG(String filePath) { ... }
public void toGIF(String filePath) { ... }
public Image fromGIF(String filePath) { ... }
}相反,我通常喜欢使用类似于以下内容的模式:
public interface ImageSerializer
{
void serialize(Image src, Stream outputStream);
Image deserialize(Stream inputStream);
}
public class JPGImageSerializer : ImageSerializer
{
public void serialize(Image src, Stream outputStream) { ... }
public Image deserialize(Stream inputStream) { ... }
}
public class PNGImageSerializer : ImageSerializer
{
public void serialize(Image src, Stream outputStream) { ... }
public Image deserialize(Stream inputStream) { ... }
}
public class GIFImageSerializer : ImageSerializer
{
public void serialize(Image src, Stream outputStream) { ... }
public Image deserialize(Stream inputStream) { ... }
}现在,这个设计的一个注意事项是,序列化程序需要知道它正在序列化的对象的identity。有些人会说,这是错误的设计,因为实现泄漏到类之外。这样做的风险/回报确实取决于您,但您可以稍微调整类,以执行以下操作
public class Image
{
public void serializeTo(ImageSerializer serializer, Stream outputStream)
{
serializer.serialize(this.pixelData, outputStream);
}
public void deserializeFrom(ImageSerializer serializer, Stream inputStream)
{
this.pixelData = serializer.deserialize(inputStream);
}
}这是一个更一般的例子,因为图像通常都包含与其相关的元数据,比如压缩级别、颜色空间等,这可能会使过程复杂化。
发布于 2015-07-04 04:07:47
序列化是两个部分的问题:
尽可能地将结构与机械分开。这增加了系统的模块化。如果将关于#2的信息隐藏在类中,那么就打破了模块化,因为现在必须对类进行修改,以跟上序列化的新方法(如果它们出现的话)。
在图像序列化的上下文中,您会将序列化的信息与类本身分开,而保留在能够确定序列化格式的算法中--因此,JPEG、PNG、BMP等不同的类。如果明天会出现一种新的序列化算法,您只需编写算法和类契约不变的代码。
在IPC上下文中,您可以将类保持独立,然后选择性地声明序列化所需的信息(通过注释/属性)。然后,您的序列化算法可以决定是使用JSON、Google缓冲区还是使用XML进行序列化。它甚至可以决定是使用Jackson解析器还是自定义解析器--当您以模块化的方式进行设计时,您可以轻松地获得许多选项!
https://softwareengineering.stackexchange.com/questions/288678
复制相似问题