2009-05-26 8 views
0

J'écris un éditeur graphique simple pour un projet universitaire en utilisant C#.
J'ai créé une hiérarchie où chaque type de forme - cercles, rectangles, ellipses, ... - est hérité d'une forme de classe de base, il contient une couleur de forme comme un champ protégé.
Est-ce une bonne idée de diviser chaque forme graphique en deux parties - sa géométrie et ses composants de rendu?


public abstract class Shape { 
     protected Color color; 

     public Shape(Color c) { 
      color = c; 
     } 

     public Color FigureColor { 
      get { return color; } 
      protected set { color = value; } 
     } 

     public abstract void render(Bitmap canvasToDrawOn); 

     public abstract void unrender(Bitmap canvasToDrawOn); 

     public abstract void renderPrototype(Bitmap canvasToDrawOn); 
    } 

L'idée est que je veux que chaque type de forme pour encapsuler `s une partie de la géométrie, par exemple:


public class TwoDPoint: TwoDShape { 
     Point2DGeometry point; 

     public TwoDPoint(Color c, Point2DGeometry p): base(c) { 
      point = new Point2DGeometry(p); 
     } 

public struct Point2DGeometry { 
     Int32 x; 
     Int32 y; 

     public Point2DGeometry(Int32 X, Int32 Y) { 
      x = X; 
      y = Y; 
     } 

     public Point2DGeometry(Point2DGeometry rhs) { 
      x = rhs.Abscissa; 
      y = rhs.Ordinate; 
     } 

     public Int32 Abscissa { 
      get { return x; } 
      private set { x = value; } 
     } 

     public Int32 Ordinate { 
      get { return y; } 
      private set { y = value; } 
     } 
    } 

classe Ellipse encapsule EllipseGeometry, etc.
Est-ce une bonne décision en termes de conception OO, et si c'est le cas, peut-être est-ce la meilleure idée de créer une hiérarchie parallèle de ces types de géométrie seulement?

Répondre

1

Je pense que la réponse est oui, car elle suit la trace du motif MVC vénéré.

Un autre avantage est qu'il vous donne la possibilité d'échanger des bibliothèques graphiques sans avoir à réécrire toutes ces classes géométriques de base. Utilisez une interface pour rendre cela encore plus facile à faire.

0

Je dirais que cela dépend. Allez-vous réutiliser vos objets de géométries en dehors de vos objets de forme, ou partager des objets de géométrie en tant que Flyweights? Si ce n'est pas le cas, vous risquez de compliquer inutilement la hiérarchie de votre classe.

Vous cherchez sur votre code, vous pouvez également considérer les points suivants:

  1. Avoir une sorte de convention de nommage entre vos champs privés et vos biens publics. Il ne sert à rien de s'habituer à Abscissa/Ordinate lorsque vos variables privées sont x/y et que votre constructeur prend X/Y. Ditto Color et FigureColor en forme.

  2. En forme, pourquoi protéger la "couleur", lorsque "FigureColor" est également protégé? Dans la plupart des API (et vous pouvez considérer votre classe abstraite comme une API pour ses classes dérivées), vous souhaiterez minimiser la confusion des membres à utiliser lors du changement d'état. Dans cet exemple particulier, je ferais très probablement une "couleur" privée.

  3. Surveillez les "classes internes" dans votre hiérarchie de classe qui n'ajoutent aucune valeur. Par exemple, vous avez une classe Shape abstraite, et à partir de son apparence, TwoDShape. Quelle est la différence entre les deux? Avez-vous un support pour 3 dimensions? Est-ce que votre arbre d'héritage ressemble plus à un bâton?

HTH, et bonne chance pour votre projet.

Questions connexes