In genere evito che la classe sappia come serializzare se stessa, per un paio di ragioni. Innanzitutto, se si desidera (de) serializzare da / verso un formato diverso, ora è necessario inquinare il modello con quella logica aggiuntiva. Se si accede al modello tramite un'interfaccia, si inquina anche il contratto.
public class Image
{
public void toJPG(String filePath) { ... }
public Image fromJPG(String filePath) { ... }
}
Ma cosa succede se si desidera serializzare da / verso un PNG e GIF? Ora la classe diventa
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) { ... }
}
Invece, in genere mi piace usare un modello simile al seguente:
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) { ... }
}
Ora, a questo punto, uno degli avvertimenti con questo design è che i serializzatori devono conoscere identity
l'oggetto che sta serializzando. Alcuni direbbero che si tratta di una cattiva progettazione, poiché l'implementazione perde al di fuori della classe. Il rischio / premio di questo dipende davvero da te, ma potresti leggermente modificare le lezioni per fare qualcosa del genere
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);
}
}
Questo è più un esempio generale, poiché le immagini di solito hanno metadati che lo accompagnano; cose come livello di compressione, spazio colore, ecc. che possono complicare il processo.