首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >序列化和反序列化应由被序列化的类负责吗?

序列化和反序列化应由被序列化的类负责吗?
EN

Software Engineering用户
提问于 2015-07-04 00:41:39
回答 2查看 9.4K关注 0票数 20

我目前正处于C# .NET应用程序的几个模型类的(重新)设计阶段。(模型如MVC中的M)。模型类已经有了大量精心设计的数据、行为和相互关系。我正在将模型从Python重写为C#。

在以前的Python模型中,我想我看到了一个疣。每个模型都知道如何序列化自己,序列化逻辑与任何类的其余行为无关。例如,想象一下:

  • 具有Image类的.toJPG(String filePath) .fromJPG(String filePath)方法
  • ImageMetaData类,其中包含.toString().fromString(String serialized)方法。

您可以想象这些序列化方法是如何与类的其他部分不结合的,但是只能保证类知道足够的数据来序列化自己。

类知道如何序列化和反序列化自身是一种常见的实践吗?还是我错过了一个常见的模式?

EN

回答 2

Software Engineering用户

回答已采纳

发布于 2015-07-04 03:22:35

出于以下几个原因,我通常避免让类知道如何序列化自己。首先,如果您想(反)序列化到/从不同的格式,您现在需要污染模型的额外的逻辑。如果模型是通过接口访问的,那么您也会污染合同。

代码语言:javascript
运行
复制
public class Image
{
    public void toJPG(String filePath) { ... }

    public Image fromJPG(String filePath) { ... }
}

但是,如果您想将其序列化到/从PNG和GIF中序列化呢?现在这个班变成

代码语言:javascript
运行
复制
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) { ... }
}

相反,我通常喜欢使用类似于以下内容的模式:

代码语言:javascript
运行
复制
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。有些人会说,这是错误的设计,因为实现泄漏到类之外。这样做的风险/回报确实取决于您,但您可以稍微调整类,以执行以下操作

代码语言:javascript
运行
复制
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);
    }
}

这是一个更一般的例子,因为图像通常都包含与其相关的元数据,比如压缩级别、颜色空间等,这可能会使过程复杂化。

票数 21
EN

Software Engineering用户

发布于 2015-07-04 04:07:47

序列化是两个部分的问题:

  1. 有关如何实例化类(又名结构)的知识。
  2. 有关如何持久化/传递实例化类(又名力学)所需信息的知识。

尽可能地将结构与机械分开。这增加了系统的模块化。如果将关于#2的信息隐藏在类中,那么就打破了模块化,因为现在必须对类进行修改,以跟上序列化的新方法(如果它们出现的话)。

在图像序列化的上下文中,您会将序列化的信息与类本身分开,而保留在能够确定序列化格式的算法中--因此,JPEG、PNG、BMP等不同的类。如果明天会出现一种新的序列化算法,您只需编写算法和类契约不变的代码。

在IPC上下文中,您可以将类保持独立,然后选择性地声明序列化所需的信息(通过注释/属性)。然后,您的序列化算法可以决定是使用JSON、Google缓冲区还是使用XML进行序列化。它甚至可以决定是使用Jackson解析器还是自定义解析器--当您以模块化的方式进行设计时,您可以轻松地获得许多选项!

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/288678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档