I need to design a class hierarchy for my C# project. Basically, class' functionalities are similar to WinForms classes so let's take WinForms toolkit as an example. (However, I can't use WinForms or WPF.)
There are some core properties and functionalities that every class needs to provide. Dimensions, position, color, visibility (true/false), Draw method, etc.
I need design advice I have used a design with an abstract base class and interfaces that are not really types but more like behaviors. Is this a good design? If not, what would be a better design.
The code looks like this:
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();
}
Some Controls can contain other Controls, some can be only contained (as children) so I'm thinking of making two interfaces for these functionalities:
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 controls display text so this also goes into interface:
interface ITextHolder
{
string Text { get; set; }
int TextPositionX { get; set; }
int TextPositionY { get; set; }
int TextWidth { get; }
int TextHeight { get; }
void DrawText();
}
Some Controls can be docked inside their parent Control so:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
...and now let's create some concrete classes:
class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}
The first "problem" I can think of here is that the interfaces are basically set in stone once they get published. But let's assume I will be able to make my interfaces good enough to avoid need of making changes to them in the future.
Another issue I see in this design is that every of these classes would need to implement it's interfaces and duplication of code will quickly occur. For example in Label and Button the DrawText() method derives from the ITextHolder interface or in every class derived from IContainer management of children.
My solution for this issue is to implement this "duplicated" functionalities in dedicated adapters and forward calls to them. So both Label and Button would have a TextHolderAdapter member that would be called inside methods inherited from the ITextHolder interface.
I think this design should shield me from having to many common functionalities in the base class which could quickly get bloated with virtual methods and unnecessary "noise code". Changes of behavior would be accomplished by extending adapters and not Control-derived classes.
I think this is called the "Strategy" pattern and although there are millions of questions and answers on that topic, I would like to ask you for your opinions as to what I take into consideration for this design and what flaws you can think of in my approach.
I should add that there is an almost 100% chance that future requirements will call for new classes and new functionalities.
System.ComponentModel.Component
orSystem.Windows.Forms.Control
or any of the other existing base classes? Why do you need to create your own control hierarchy and define all these functions again from scratch?IChild
seems like a horrible name.