Я вообще избегаю, чтобы класс знал, как сериализовать себя, по нескольким причинам. Во-первых, если вы хотите (де) сериализовать в / из другого формата, теперь вам нужно загрязнить модель этой дополнительной логикой. Если модель доступна через интерфейс, вы также загрязняете контракт.
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);
}
}
Это более общий пример, поскольку изображения обычно содержат метаданные, которые сопровождают его; такие вещи, как уровень сжатия, цветовое пространство и т. д., которые могут усложнить процесс.