Necesito diseñar una jerarquía de clases para mi proyecto C #. Básicamente, las funcionalidades de la clase son similares a las clases de WinForms, así que tomemos el kit de herramientas de WinForms como ejemplo. (Sin embargo, no puedo usar WinForms o WPF).
Hay algunas propiedades y funcionalidades centrales que cada clase necesita proporcionar. Dimensiones, posición, color, visibilidad (verdadero / falso), método de dibujo, etc.
Necesito consejos de diseño. He utilizado un diseño con una clase base abstracta e interfaces que no son realmente tipos, sino más bien comportamientos. ¿Es este un buen diseño? Si no, cuál sería un mejor diseño.
El código se ve así:
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();
}
Algunos controles pueden contener otros controles, algunos solo pueden estar contenidos (como hijos), así que estoy pensando en hacer dos interfaces para estas funcionalidades:
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);
}
WinForms controla el texto de la pantalla, por lo que esto también entra en la interfaz:
interface ITextHolder
{
string Text { get; set; }
int TextPositionX { get; set; }
int TextPositionY { get; set; }
int TextWidth { get; }
int TextHeight { get; }
void DrawText();
}
Algunos controles se pueden acoplar dentro de su control principal para que:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
... y ahora creemos algunas clases concretas:
class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}
El primer "problema" en el que puedo pensar aquí es que las interfaces se establecen básicamente en piedra una vez que se publican. Pero supongamos que podré hacer que mis interfaces sean lo suficientemente buenas para evitar la necesidad de hacer cambios en ellas en el futuro.
Otro problema que veo en este diseño es que cada una de estas clases necesitaría implementar sus interfaces y la duplicación de código ocurrirá rápidamente. Por ejemplo, en Label and Button, el método DrawText () se deriva de la interfaz ITextHolder o de cada clase derivada de la administración de IContainer de niños.
Mi solución para este problema es implementar estas funcionalidades "duplicadas" en adaptadores dedicados y reenviar llamadas a ellos. Por lo tanto, Label y Button tendrían un miembro TextHolderAdapter que se llamaría dentro de los métodos heredados de la interfaz ITextHolder.
Creo que este diseño debería protegerme de tener muchas funcionalidades comunes en la clase base que podrían hincharse rápidamente con métodos virtuales y un "código de ruido" innecesario. Los cambios de comportamiento se realizarían ampliando los adaptadores y no las clases derivadas de Control.
Creo que esto se llama el patrón "Estrategia" y, aunque hay millones de preguntas y respuestas sobre ese tema, me gustaría pedirle su opinión sobre lo que tengo en cuenta para este diseño y qué defectos puede pensar en mi acercamiento.
Debo agregar que hay casi un 100% de posibilidades de que los requisitos futuros requieran nuevas clases y nuevas funcionalidades.
IChild
Parece un nombre horrible.
System.ComponentModel.Component
o deSystem.Windows.Forms.Control
cualquiera de las otras clases base existentes? ¿Por qué necesita crear su propia jerarquía de control y definir todas estas funciones nuevamente desde cero?