Por lo general, evito que la clase sepa cómo serializarse, por un par de razones. Primero, si desea (des) serializar a / desde un formato diferente, ahora necesita contaminar el modelo con esa lógica adicional. Si se accede al modelo a través de una interfaz, también contaminará el contrato.
public class Image
{
public void toJPG(String filePath) { ... }
public Image fromJPG(String filePath) { ... }
}
Pero, ¿qué pasa si desea serializarlo a / desde un PNG y GIF? Ahora la clase se convierte
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) { ... }
}
En cambio, normalmente me gusta usar un patrón similar al siguiente:
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) { ... }
}
Ahora, en este punto, una de las advertencias con este diseño es que los serializadores necesitan conocer identity
el objeto que está serializando. Algunos dirían que este es un mal diseño, ya que la implementación se filtra fuera de la clase. El riesgo / recompensa de esto depende realmente de usted, pero podría modificar ligeramente las clases para hacer 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 es más un ejemplo general, ya que las imágenes generalmente tienen metadatos que lo acompañan; cosas como el nivel de compresión, el espacio de color, etc., que pueden complicar el proceso.
ImageSerializer
, se escriben más implementaciones de la interfaz), laImageSerializer
interfaz también necesitará crecer. EJ: Un nuevo formato admite compresión opcional, los anteriores no lo hicieron -> agregar configuración de compresión a laImageSerializer
interfaz. Pero luego, los otros formatos están llenos de características que no se aplican a ellos. Cuanto más lo pienso, menos creo que la herencia se aplique aquí.void serialize(Image image, Stream outputStream, SerializerSettings settings);
Entonces es solo un caso de conectar la compresión existente y la lógica de metadatos al nuevo método.La serialización es un problema de dos partes:
En la medida de lo posible, la estructura debe mantenerse separada de la mecánica . Esto aumenta la modularidad de su sistema. Si entierra la información en el n. ° 2 dentro de su clase, entonces rompe la modularidad porque ahora su clase debe modificarse para mantener el ritmo de las nuevas formas de serialización (si aparecen).
En el contexto de la serialización de imágenes, mantendría la información sobre la serialización separada de la clase misma y la mantendría más bien en los algoritmos que pueden determinar el formato de serialización, por lo tanto, diferentes clases para JPEG, PNG, BMP, etc. aparece el algoritmo de serialización, simplemente codifica ese algoritmo y su contrato de clase permanece sin cambios.
En el contexto de IPC, puede mantener su clase separada y luego declarar selectivamente la información que se necesita para la serialización (por anotaciones / atributos). Luego, su algoritmo de serialización puede decidir si usar JSON, Google Protocol Buffers o XML para la serialización. Incluso puede decidir si usar el analizador Jackson o su analizador personalizado: ¡hay muchas opciones que obtendrá fácilmente cuando diseñe de forma modular!
fuente