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 principales que cada clase debe 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 comportamientos similares. ¿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 niños), 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);
}
Los controles de WinForms muestran el texto, 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, por lo que:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
... y ahora vamos a crear 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" que se me ocurre aquí es que las interfaces están básicamente escritas en piedra una vez que se publican. Pero supongamos que podré hacer que mis interfaces sean lo suficientemente buenas para evitar la necesidad de realizar 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 se producirá rápidamente. Por ejemplo, en Label and Button, el método DrawText () se deriva de la interfaz ITextHolder o en cada clase derivada de la gestión de niños de IContainer.
Mi solución para este problema es implementar estas funcionalidades "duplicadas" en adaptadores dedicados y reenviarlas. Por lo tanto, tanto la etiqueta como el botón tendrían un miembro de TextHolderAdapter que se llamaría dentro de los métodos heredados de la interfaz de ITextHolder.
Creo que este diseño debería protegerme de tener que 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 lograrían extendiendo los adaptadores y no las clases derivadas de Control.
Creo que a esto se le llama el patrón de "Estrategia" y aunque hay millones de preguntas y respuestas sobre ese tema, me gustaría preguntarle sus opiniones sobre lo que tomo en cuenta para este diseño y qué fallas puede hacer. pensar en mi enfoque.
Debo agregar que hay una probabilidad de casi el 100% de que los requisitos futuros exijan nuevas clases y nuevas funcionalidades.