Devo progettare una gerarchia di classi per il mio progetto C #. Fondamentalmente, le funzionalità della classe sono simili alle classi WinForms, quindi prendiamo ad esempio il toolkit WinForms. (Tuttavia, non posso usare WinForms o WPF.)
Ci sono alcune proprietà e funzionalità di base che ogni classe deve fornire. Dimensioni, posizione, colore, visibilità (vero / falso), metodo di disegno, ecc.
Ho bisogno di consigli di progettazione Ho usato un design con una classe base astratta e interfacce che non sono realmente tipi ma più simili a comportamenti. È un buon design? In caso contrario, quale sarebbe un design migliore.
Il codice è simile al seguente:
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();
}
Alcuni controlli possono contenere altri controlli, alcuni possono essere contenuti solo (come figli), quindi sto pensando di creare due interfacce per queste funzionalità:
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 controlla la visualizzazione del testo, quindi anche questo va nell'interfaccia:
interface ITextHolder
{
string Text { get; set; }
int TextPositionX { get; set; }
int TextPositionY { get; set; }
int TextWidth { get; }
int TextHeight { get; }
void DrawText();
}
Alcuni controlli possono essere agganciati all'interno del loro controllo genitore in modo che:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
... e ora creiamo alcune classi concrete:
class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}
Il primo "problema" che mi viene in mente qui è che le interfacce sono fondamentalmente incastonate una volta pubblicate. Ma supponiamo che sarò in grado di rendere le mie interfacce abbastanza buone da evitare la necessità di apportarle modifiche in futuro.
Un altro problema che vedo in questo progetto è che ognuna di queste classi dovrebbe implementare le sue interfacce e si verificherà rapidamente la duplicazione del codice. Ad esempio, in Label and Button il metodo DrawText () deriva dall'interfaccia ITextHolder o in ogni classe derivata dalla gestione IContainer dei bambini.
La mia soluzione a questo problema è implementare queste funzionalità "duplicate" in adattatori dedicati e inoltrare le chiamate a loro. Quindi sia Label che Button avrebbero un membro TextHolderAdapter che verrebbe chiamato all'interno dei metodi ereditati dall'interfaccia ITextHolder.
Penso che questo progetto dovrebbe proteggermi dall'avere molte funzionalità comuni nella classe base che potrebbero rapidamente gonfiarsi con metodi virtuali e "noise code" non necessari. I cambiamenti di comportamento verrebbero realizzati estendendo gli adattatori e non le classi derivate dal controllo.
Penso che questo sia chiamato il modello "Strategia" e sebbene ci siano milioni di domande e risposte su quell'argomento, vorrei chiederti le tue opinioni su ciò che prendo in considerazione per questo disegno e su quali difetti puoi pensare il mio approccio.
Vorrei aggiungere che esiste una probabilità quasi del 100% che i requisiti futuri richiedano nuove classi e nuove funzionalità.
IChild
sembra un nome orribile.
System.ComponentModel.Component
o da unaSystem.Windows.Forms.Control
qualsiasi delle altre classi base esistenti? Perché è necessario creare la propria gerarchia di controllo e definire nuovamente tutte queste funzioni da zero?