J'ai besoin de concevoir une hiérarchie de classes pour mon projet C #. Fondamentalement, les fonctionnalités des classes sont similaires aux classes WinForms, prenons donc la boîte à outils WinForms comme exemple. (Cependant, je ne peux pas utiliser WinForms ou WPF.)
Il y a quelques propriétés et fonctionnalités de base que chaque classe doit fournir. Dimensions, position, couleur, visibilité (vrai / faux), méthode de dessin, etc.
J'ai besoin de conseils de conception J'ai utilisé une conception avec une classe de base abstraite et des interfaces qui ne sont pas vraiment des types mais plutôt des comportements. Est-ce un bon design? Sinon, quelle serait une meilleure conception.
Le code ressemble à ceci:
abstract class Control
{
public int Width { get; set; }
public int Height { get; set; }
public int BackColor { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int BorderWidth { get; set; }
public int BorderColor { get; set; }
public bool Visible { get; set; }
public Rectangle ClipRectange { get; protected set; }
abstract public void Draw();
}
Certains contrôles peuvent contenir d'autres contrôles, certains ne peuvent être contenus (qu'en tant qu'enfants), donc je pense à faire deux interfaces pour ces fonctionnalités:
interface IChild
{
IContainer Parent { get; set; }
}
internal interface IContainer
{
void AddChild<T>(T child) where T : IChild;
void RemoveChild<T>(T child) where T : IChild;
IChild GetChild(int index);
}
Les contrôles WinForms affichent du texte, donc cela va aussi dans l'interface:
interface ITextHolder
{
string Text { get; set; }
int TextPositionX { get; set; }
int TextPositionY { get; set; }
int TextWidth { get; }
int TextHeight { get; }
void DrawText();
}
Certains contrôles peuvent être ancrés dans leur contrôle parent afin:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
... et maintenant créons des classes concrètes:
class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}
Le premier "problème" auquel je peux penser ici est que les interfaces sont fondamentalement figées une fois publiées. Mais supposons que je serai en mesure de rendre mes interfaces suffisamment bonnes pour éviter d'avoir à les modifier à l'avenir.
Un autre problème que je vois dans cette conception est que chacune de ces classes aurait besoin d'implémenter ses interfaces et la duplication de code se produira rapidement. Par exemple, dans Label et Button, la méthode DrawText () dérive de l'interface ITextHolder ou de chaque classe dérivée de la gestion IContainer des enfants.
Ma solution à ce problème consiste à implémenter ces fonctionnalités "dupliquées" dans des adaptateurs dédiés et à leur renvoyer les appels. Ainsi, Label et Button auraient tous deux un membre TextHolderAdapter qui serait appelé à l'intérieur de méthodes héritées de l'interface ITextHolder.
Je pense que cette conception devrait me protéger d'avoir de nombreuses fonctionnalités communes dans la classe de base qui pourraient rapidement être gonflées avec des méthodes virtuelles et un "code de bruit" inutile. Les changements de comportement seraient accomplis en étendant les adaptateurs et non les classes dérivées de Control.
Je pense que cela s'appelle le modèle de "stratégie" et bien qu'il y ait des millions de questions et réponses sur ce sujet, je voudrais vous demander votre avis sur ce que je prends en considération pour cette conception et sur les défauts auxquels vous pouvez penser mon approche.
Je dois ajouter qu'il y a presque 100% de chances que les exigences futures appellent de nouvelles classes et de nouvelles fonctionnalités.
IChild
semble être un nom horrible.
System.ComponentModel.Component
ouSystem.Windows.Forms.Control
de l'une des autres classes de base existantes? Pourquoi devez-vous créer votre propre hiérarchie de contrôle et définir à nouveau toutes ces fonctions à partir de zéro?