いくつかの理由から、通常、クラスに自分自身をシリアル化する方法を知ってもらうことは避けます。最初に、異なるフォーマットとの間で(デ)シリアライズしたい場合、その余分なロジックでモデルを汚染する必要があります。インターフェースを介してモデルにアクセスすると、契約も汚染されます。
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) { ... }
}
さて、この時点で、この設計の注意点の1つは、シリアライザーがシリアライズする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);
}
}
画像は通常、それに付随するメタデータを持っているため、これはより一般的な例です。プロセスを複雑にする可能性のある圧縮レベル、色空間などのようなもの。