2009-05-26 1 views
0

Ich schreibe einen einfachen Grafikeditor für ein Universitätsprojekt mit C#.
Ich habe eine Hierarchie erstellt, in der jeder Formtyp - Kreise, Rechtecke, Ellipsen, ... - von einer Basisklasse Shape geerbt wird und eine Formfarbe als geschütztes Feld enthält.
Ist es eine gute Idee, jede grafische Form in zwei Teile zu teilen - ihre Geometrie und Rendering-Komponenten?


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); 
    } 

Die Idee ist, dass ich jede Art von Form will `s Geometrie Teil zu kapseln, zum Beispiel:


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; } 
     } 
    } 

Ellipse Klasse EllipseGeometry kapseln wird usw.
Ist es ein gute Entscheidung in Bezug auf OO-Design, und wenn es ist, ist es vielleicht die bessere Idee, eine parallele Hierarchie dieser Geometrie nur Typen zu erstellen?

Antwort

1

Ich denke, die Antwort ist ja, weil es in der Spur folgt, die vom verehrten MVC-Muster festgelegt wird.

Ein weiterer Vorteil besteht darin, dass Sie die Möglichkeit haben, Grafikbibliotheken auszuwechseln, ohne alle geometrischen Basisklassen neu schreiben zu müssen. Verwenden Sie eine Schnittstelle, um das noch einfacher zu machen.

0

Ich würde sagen, dass es abhängt. Werden Sie Ihre Geometries-Objekte außerhalb Ihrer Shape-Objekte wiederverwenden oder Geometry-Objekte als Flyweights freigeben? Wenn nicht, verkomplizieren Sie möglicherweise Ihre Klassenhierarchie unnötig.

  1. Nachdem eine Art Namenskonvention zwischen Ihren privaten Feldern und Ihren öffentlichen Eigenschaften:

    Mit Blick auf Ihrem Code können Sie auch die folgenden betrachten. Es macht keinen Sinn, mit Abszisse/Ordinate zu experimentieren, wenn Ihre privaten Variablen x/y sind und Ihr Konstruktor X/Y nimmt. Ditto Color und FigureColor in Form.

  2. In Shape, warum "Farbe" geschützt, wenn "FigureColor" auch einen geschützten Setter hat? In den meisten APIs (und Sie können sich Ihre abstrakte Klasse als API für abgeleitete Klassen vorstellen) möchten Sie die Verwirrung der Mitglieder, die beim Ändern des Status verwendet werden sollen, minimieren. In diesem speziellen Beispiel würde ich "Farbe" höchstwahrscheinlich privat machen.

  3. Achten Sie auf "interne Klassen" in Ihrer Klassenhierarchie, die keinen Wert hinzufügen. Zum Beispiel haben Sie eine abstrakte Shape-Klasse, und von dem Aussehen auch, TwoDShape. Was ist der Unterschied zwischen den beiden? Hast du Unterstützung für 3 Dimensionen? Sieht Ihr Vererbungsbaum mehr wie ein Stock aus?

HTH, und viel Glück mit Ihrem Projekt.

Verwandte Themen