2010-11-11 38 views
1

J'ai une famille de classes dont je pense qu'elle a besoin d'encapsulation sur les méthodes de création. Prenons, par exemple:Besoin d'aide avec la création d'une classe d'usine pour encapsuler la création d'objets

public abstract class File 
{ 
    protected File(string fileName) 
    { 
     Name = fileName; 
    } 
    string Name {get; set;} 
} 

public class ImageFile : File 
{ 
    protected ImageFile(string fileName, int width, int Height) :base(fileName) 
    { 
     Height = height; 
     Width = width; 
    } 

    int Height {get; set;} 
    int Width {get; set;} 
} 

public class WordFile : File 
{ 
    protected WordFile(string fileName, int wordCount) :base(fileName) 
    { 
     WordCount = wordCount; 
    } 

    int WordCount {get; set;} 
} 

Compte tenu de cette hiérarchie de classes, ce qui est la meilleure méthode pour moi de résumer la méthode de création de chaque classes distinctes? Il serait utile si vous pouvez fournir des exemples d'utilisation d'une classe d'usine?

Merci beaucoup

Modifier

Une idée que j'avais l'esprit i est une méthode d'usine dans la classe abstraite qui retourne la classe concrète. par exemple

public abstract class File 
    { 
     protected File(string fileName) 
     { 
     .... 
     } 

     string Name {get; set;} 
     public static File Create(string fileName) 
     { 
      if(filename.Contains("jpg") 
      { 
       return new ImageFile(...); 
      } 
      .... 
     } 
    } 

Mais dans cet exemple je ne suis pas sûr de savoir comment je peux passer les paramètres unqiue pour chacun des types de béton. à-dire largeur, hauteur, WordCount ...

+1

Les usines ont un coût, vous ne devriez donc les utiliser que si elles vont ajouter de la valeur. Quel problème attendez-vous qu'ils résolvent dans votre exemple? Quel type de construction de code voulez-vous autoriser? 'File.Create (...)', retourne une de tes sous-classes? Si oui, comment cela va-t-il être mis en œuvre? Comment l'usine saura-t-elle quelle classe instancier? –

+0

Edité ma question pour élaborer un peu. L'idée est de passer le nomFichier et l'usine va "comprendre" ce que le type concret est basé sur l'extension du fichier. Mais je suis coincé sur la façon de traiter les paramètres de type concret. – Fixer

+0

Ceci est probablement hors sujet, mais vous devriez probablement utiliser 'Path.GetExtension (fileName) .toUpperInvariant() ==" .JPG "' au lieu de simplement utiliser 'fileName.Contains'. Cela permettra des cas mixtes comme "file.JpG", ou une utilisation non-extension comme "listofjpgfiles.txt". – MiffTheFox

Répondre

2

Que diriez-vous de créer une usine différente pour chacun de ces types de fichiers? Votre méthode File.Create(...) peut choisir laquelle invoquer, puis chaque fabrique serait responsable de la lecture d'un type particulier de fichier, en créant les données nécessaires pour générer l'objet File que vous voulez avoir et en le renvoyant.

public static File Create(string fileName) 
{ 
    var factory = GetFactory(fileName); 
    return factory.CreateFile(fileName); 
} 

public static IFileFactory GetFactory(string fileName) 
{ 
    if(Path.GetExtension(fileName).toUpperInvariant() == ".JPG") 
    { 
     return new ImageFileFactory(); 
    } 
    //... 
} 

public interface IFileFactory 
{ 
    File CreateFile(string fileName); 
} 
public class ImageFileFactory : IFileFactory 
{ 
    public File CreateFile(string fileName) 
    { 
     int width = GetWidth(fileName); 
     int height = GetHeight(fileName); 
     return new ImageFile(fileName, width, height); 
    } 
} 
+0

Très intéressant! Est-ce aussi connu comme le modèle d'usine abstraite? – Fixer

+0

Bump, mais serait mieux servi avec un fichier DTO FileData pour le constructeur methinks. – annakata

+0

@Fixer: http://en.wikipedia.org/wiki/Abstract_factory_pattern – annakata

0

Vous avez eu deux options, je pense:

  1. Définir une sorte d'objet (comme un dictionnaire) qui contient les paramètres que chaque différents instance devrait avoir. Le code qui appelle la méthode d'usine sera responsable de la construction du dictionnaire correctement (vous devez probablement vous assurer que les clés sont des constantes définies dans chacune des sous-classes) et de le transmettre. Le constructeur pour chacune des sous-classes sera responsable de la validation de l'objet et de s'assurer que tout ce dont ils ont besoin est présent. Si ce n'est pas le cas, ils devraient émettre une exception fournissant des informations raisonnables.

  2. Si les paramètres ne sont pas directement requis pour la construction d'un objet, vous pouvez les ajouter en tant que propriétés. Le code appelant serait responsable de la définition de ces propriétés et les sous-classes devraient valider les propriétés qui ont été définies lorsqu'elles ont besoin des propriétés. Si ce n'est pas le cas, ils devraient à nouveau émettre une exception fournissant des informations raisonnables.

La plus grande chose que vous allez perdre ici est la compilation de vérification des erreurs de ces paramètres - si le code d'appel ne fournit pas, par exemple, le paramètre de nombre de mots pour la classe WordFile, il a gagné Ne sois pas une erreur de compilateur.

0

Il semble que vous essayez de créer des objets de classes qui ont des paramètres différents pour leurs constructeurs. Le motif Usine ne vous aide pas à résoudre cela. Cela aide à résoudre le fait qu'en fonction du nom de fichier, il créera un objet approprié. Pour leur passer différents paramètres, vous devrez le faire une fois les objets créés. Une solution peut être d'avoir une liste ou un tableau d'arguments à transmettre et votre usine peut déterminer le type d'objet à créer, puis utiliser la liste de paramètres ou le tableau pour créer l'objet désiré. Par exemple

List<int> param = new List<int>(); 
param.Add(200); //So add as many parameters as you want 
//The factory will simply pass those to the objects it is creating 
//And then pass this pass this param to your File.Create() method 
File.Create(param); 

Le seul avantage ici d'utiliser une usine ici est que votre code sera indépendant des implémentations spécifiques des différentes classes de type de fichier que vous la mise en œuvre. Sinon, je vous suggère de ne pas utiliser ce motif et de créer simplement vos objets directement car vous savez déjà quoi créer.

+0

Je m'interrogeais à ce sujet mais je pense qu'il y a des avantages à utiliser une usine parce que j'encapsule l'instanciation. Dire que j'avais plusieurs centaines de fichiers à traiter, je voudrais certainement éviter d'effectuer les contrôles d'extension de fichier dans le code client et laisser l'usine gérer, si possible ... – Fixer