2009-01-24 16 views
2

J'ai besoin d'enregistrer un fichier image dans différents formats. La liste des formats est sujette à changement assez souvent, donc je souhaite que la sauvegarde soit très extensible. En outre, la sauvegarde peut avoir lieu dans de nombreux endroits (disque dur, ftp, http, etc.). La liste des emplacements va changer très souvent aussi.Modèle de conception adapté à la tâche

Je pensais que j'utiliser une classe d'image de base et de nombreuses classes pour chaque format dérivant:

ImageBase {} 
JpegImage : ImageBase {} 
TiffImage : ImageBase{} 

et gérer l'enregistrement dans chaque sous-classe appropriée au format. Est-ce une bonne dessiccation?

En outre, comment puis-je attacher un mécanisme d'enregistrement extensible d'emplacement (Ftp, partage de fichiers, etc)?

Je voudrais quelque chose comme ceci:

var image=ImageBase.GetImageFromDisk(path); 
//some casting to subclass maybe?? 
var tiffImage=image as TiffImage; 
tiffImage.Location=new FtpLocation();//not sure if this is a good idea 
tiffImage.Save(); 

Le problème ici, est que la mise en œuvre d'image concrète ne devrait pas connaître ou se soucier de l'emplacement de sauvegarde. En appelant Save(); sur la sous-classe d'image, je voudrais déléguer le travail à une certaine classe, comme FtpLocation.

S'il vous plaît des conseils sur la façon de mettre les pièces ensemble.

Merci.

Valentin.

+0

Les femmes ne sont-elles pas autorisées à répondre à cette question? ;) –

+0

+1 pour la remarque/question de Matt Hamilton –

+0

Édité pour PC (Correct politiquement), ce qui est impair car je suis la dernière personne à être PC (dans tous les sens de l'acronyme). – UnkwnTech

Répondre

5

Premièrement, j'implémenterais des flux sur votre image. De cette façon, vous pouvez créer un constructeur à partir d'un flux, et une méthode pour créer un flux à l'une de vos sous-classes "image".

De plus, je voudrais créer votre « sauver » l'infrastructure d'accepter simplement les flux et les écrire sur vos techniques appropriées (ftp, fichier, etc.)

De cette façon, vous vous retrouvez avec des images extensibles (si vous pouvez obtenir un flux vers ce que vous pouvez faire beaucoup, beaucoup de choses) et vous vous retrouvez avec une infrastructure d'épargne qui est également extensible (tout ce qui peut aller à un flux peut être sauvegardé)

EDIT: Personnellement, une méthode de sauvegarde sur un L'objet de type de données semble être au mauvais endroit, mais sans connaître votre système complet, je ne peux pas le dire à coup sûr. Juste mon 2c.

1

Il me semble que la classe concrète ne devrait traiter que les données brutes; cela peut être l'écriture d'un fichier local (qui est ensuite géré par le code de base) ou d'un flux.

Par exemple, peut-être quelque chose comme:

public void Save() 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = Location.OpenWrite(); 
    Save(stream); 
    stream.Close(); 
} 

protected abstract void Save(Stream stream); 

Ainsi, le Location est chargé de fournir un flux (qui pourrait être un flux de mémoire, un flux de transport, un flux de fichier temporaire, etc.), et en faisant le cas échéant travail supplémentaire lorsque ce flux est fermé (en encapsulant un flux interne via un motif décorateur). Tout ce que fait la sous-classe est d'écrire dans un flux.

Le chargement est un peu plus délicat, car la classe de base doit vraisemblablement (compte tenu de votre charge statique suggérée par la classe de base) jeter un coup d'œil sur le flux pour identifier le type.Mais finalement, vous pourriez avoir quelque chose de similaire:

public static ImageBase Load(Location location) 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = location.OpenRead(); 
    // TODO: wrap in a buffered/seekable stream so we can peek 
    // TODO: parse headers and resolve image type 
    ImageBase image = ... 
    image.Location = location; 
    stream.Position = 0; // rewind buffered/seekable stream 
    // (don't use Load() since we have already opened the stream) 
    image.Load(stream); 
    stream.Close(); 
    return image; 
} 
protected abstract void Load(Stream stream); 
public void Load() 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = Location.OpenRead(); 
    Load(stream); // don't need to buffer if loading from subclass 
    stream.Close(); 
} 
0

Implémentez Save() dans la classe ImageBase, et non dans les classes dérivées.

0

Je pense que l'image de sous-classement elle-même pour l'enregistrement/chargement n'est pas une bonne idée, puisque vous n'aurez pas d'instance pour appeler Load on. De plus, l'image en mémoire est assez indépendante du format original - il est absolument possible d'ouvrir jpg et de l'enregistrer en png, par exemple.

je le ferais de la façon suivante:

Image 

ImageFormat { Save(Image, Stream); Image Load(Stream); } 
JpegFormat : ImageFormat {} 
TiffFormat : ImageFormat {} 

Maintenant, pour l'emplacement vous fournir juste un moyen d'obtenir un flux de lecture et flux d'écriture.

1

Je voudrais aller un peu différemment. (La syntaxe est Java.)

public class Image { 
    public void load(byte[] imageData); 
    public byte[] getImageData(); 
} 

public class JpegImage extends Image { 
    public void load(byte[] imageData) { 
     /* decode image data. */ 
    } 

    public byte[] getImageData() { 
     /* encode and return the JPG data. */ 
    } 
} 

public class Location { 
    public Image loadImage(String uri); 
    public void saveImage(Image image); 
} 

public class HttpLocation extends Location { 
    public Image loadImage(String uri) { 
     byte[] = getData(uri); 
     if (type == JPEG) { 
      return new JpegImage().load(byte); 
     } else if (type == PNG) { 
      return new PngImage().load(byte); 
     } 
    } 
    public void saveImage(Image image) { 
     byte[] imageData = image.getImageData(); 
     /* upload. */ 
    } 
} 

La cartographie du type de contenu du serveur Web à une classe d'image pourrait également se produire d'une manière plus réutilisable dans la classe de base de l'emplacement (ou une classe d'aide complètement différent), mais qui est sur la façon Je le ferais.

0

Pour les images, je voudrais aller avec l'héritage. Pour la partie de chargement/sauvegarde, j'irais avec le modèle de conception de stratégie, de sorte que chaque image puisse avoir un algorithme de chargement et un algorithme de sauvegarde. De cette façon, vous pouvez faire varier le chargement et le processus d'enregistrement et ne pas avoir à charger et sauvegarder les méthodes de la classe Image.

Questions connexes