2009-10-05 6 views
1

J'ai une classe abstraite, Shape, et j'ai un objet Canvas que Shape utilise pour définir sa position. Je dois m'assurer que toutes les formes ont un objet Canvas, de préférence un objet Canvas qui est le même sur toutes les formes.Injection d'une ressource dans une classe abstraite

J'ai pensé à deux options:

  • Ajouter un paramètre de toile aux constructeurs de forme (il y a beaucoup)

  • Avoir une sorte d'endroit où la forme abstraite obtient son toile (quand un défaut est requis)

  • Faites toute ma construction de forme passer par une usine de quelque sorte.

Lequel est le meilleur?

J'utilise C#/.NET 3.5

Répondre

0

Pour Dependency Injection (DI) le meilleur par défaut modèle est Constructor Injection (votre première option) car il peut facilement être mis en œuvre pour assurer que les invariants de vos formes.

Il suffit d'ajouter un article à votre garde Forme cteur comme ceci:

private readonly Canvas canvas; 

protected Shape(Canvas canvas) 
{ 
    if(canvas == null) 
    { 
     throw new ArgumentNullException("canvas"); 
    } 
    this.canvas = canvas; 
} 

Cela garantit que le champ de la toile est toujours disponible etne nulle.

Vous pouvez obtenir cette propriété d'une autre manière, mais Constructo Injection est de loin le moyen le plus simple de garantir des invariants. Je choisis donc cette stratégie comme DI par défaut sauf si j'ai d'autres besoins.

0

Qu'en est-il d'avoir ICanvas biens publics qui obtient injecté par le cadre de di? Si vous avez vraiment beaucoup de classes implémentant Shape, cela signifie beaucoup de constructeurs avec le paramètre Canvas, pour la propriété vous le déclarez une fois dans Shape et l'utilisez partout.

0

Avez-vous pensé l'inverse. Je veux dire avoir un objet canvas et y ajouter des objets shape. De cette façon, tous vos objets de formes ont un point de référence commun qui est Canvas. Un objet de canevas comportant une collection de formes. De cette façon, vous pouvez effectuer des opérations courantes sur des formes telles que redimensionner toutes les formes lorsque le canevas est redimensionné.

0

j'ai eu une idée similaire SM Kamran: Vous pouvez avoir une propriété Canvas dans votre classe Shape pour indiquer la toile à laquelle cette forme appartient, et une collection Shapes dans votre classe Canvas pour contenir une collection de formes:

Voici un exemple rapide:

interface ICanvas 
{ 
    // It's a good thing to use an interface 
    // in this phase. It will allow you greater 
    // freedom later. 
} 

class Canvas : ICanvas 
{ 
    private Shape.ShapeCollection _shapes; 
    public Collection<Shape> Shapes 
    { 
     get { return _shapes; } 
    } 

    public Canvas() 
    { 
     _shapes = new Shape.ShapeCollection(this); 
    } 
} 

class Shape 
{ 
    public class ShapeCollection : Collection<Shape> 
    { 
     private readonly ICanvas _parent; 
     public ShapeCollection(ICanvas parent) 
     { 
      _parent = parent; 
     } 

     protected override void InsertItem(int index, Shape item) 
     { 
      item._canvas = _parent; 
      base.InsertItem(index, item); 
     } 

     protected override void RemoveItem(int index) 
     { 
      this[index]._canvas = null; 
      base.RemoveItem(index); 
     } 

     protected override void SetItem(int index, Shape item) 
     { 
      RemoveAt(index); 
      InsertItem(index, item); 
     } 

     protected override void ClearItems() 
     { 
      while (this.Count != 0) 
       this.RemoveAt(this.Count - 1); 
     } 
    } 

    private ICanvas _canvas; 
    public ICanvas Canvas 
    { 
     get { return _canvas; } 
    } 
} 

En ajoutant une forme à une toile, Shape.Canvas propriété sera automatiquement mis à jour:

Canvas canvas = new Canvas(); 
Shape circle = new Shape(); 

canvas.Shapes.Add(circle); 

Notez que ShapeCollection est une classe imbriquée à l'intérieur de Shape, car c'est la seule façon de définir la propriété privée _canvas.

collections génériques (comme Collection<Shape>) sont souvent utilisés pour des problèmes similaires, parce que vous pouvez passer outre leurs propriétés InsertItem/RemoveItem ajouter des fonctionnalités personnalisées lorsque la collection est en cours de modification.

Vous pouvez également créer un singleton "Empty/Default Canvas" et l'utiliser à la place de null lorsque la forme n'est pas assignée à un vrai canvas (juste pour éviter de vérifier si Shape.Canvas est nul à chaque fois).

Questions connexes