Geralmente, evito que a classe saiba como se serializar por alguns motivos. Primeiro, se você deseja (des) serializar de / para um formato diferente, agora precisa poluir o modelo com essa lógica extra. Se o modelo for acessado por meio de uma interface, você também poluirá o contrato.
public class Image
{
public void toJPG(String filePath) { ... }
public Image fromJPG(String filePath) { ... }
}
Mas e se você quiser serializá-lo para / de um PNG e GIF? Agora a turma se torna
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) { ... }
}
Em vez disso, normalmente gosto de usar um padrão semelhante ao seguinte:
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) { ... }
}
Agora, neste ponto, uma das advertências com esse design é que os serializadores precisam conhecer identity
o objeto que está serializando. Alguns diriam que esse design é ruim, pois a implementação vaza para fora da classe. O risco / recompensa é realmente de sua responsabilidade, mas você pode ajustar levemente as aulas para fazer algo como
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);
}
}
Este é mais um exemplo geral, pois as imagens geralmente têm metadados que os acompanham; coisas como nível de compactação, espaço de cores etc. que podem complicar o processo.