Мне нужно спроектировать иерархию классов для моего проекта на C #. По сути, функциональные возможности классов аналогичны классам WinForms, поэтому давайте возьмем в качестве примера инструментарий WinForms. (Однако я не могу использовать WinForms или WPF.)
Есть некоторые основные свойства и функциональные возможности, которые должен обеспечить каждый класс. Размеры, положение, цвет, видимость (true / false), метод Draw и т. Д.
Мне нужен совет по дизайну. Я использовал дизайн с абстрактным базовым классом и интерфейсами, которые на самом деле не являются типами, а больше похожи на поведение. Это хороший дизайн? Если нет, то что будет лучше дизайн.
Код выглядит так:
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();
}
Некоторые элементы управления могут содержать другие элементы управления, некоторые могут содержаться только (как дочерние элементы), поэтому я подумываю создать два интерфейса для этих функций:
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 контролирует отображение текста, так что это также входит в интерфейс:
interface ITextHolder
{
string Text { get; set; }
int TextPositionX { get; set; }
int TextPositionY { get; set; }
int TextWidth { get; }
int TextHeight { get; }
void DrawText();
}
Некоторые элементы управления могут быть закреплены внутри родительского элемента управления так:
enum Docking
{
None, Left, Right, Top, Bottom, Fill
}
interface IDockable
{
Docking Dock { get; set; }
}
... а теперь давайте создадим несколько конкретных классов:
class Panel : Control, IDockable, IContainer, IChild {}
class Label : Control, IDockable, IChild, ITextHolder {}
class Button : Control, IChild, ITextHolder, IDockable {}
class Window : Control, IContainer, IDockable {}
Первая «проблема», о которой я могу подумать, заключается в том, что интерфейсы в основном устанавливаются в камне после их публикации. Но давайте предположим, что я смогу сделать свои интерфейсы достаточно хорошими, чтобы избежать необходимости вносить в них изменения в будущем.
Другая проблема, которую я вижу в этом проекте, заключается в том, что каждый из этих классов должен будет реализовывать свои интерфейсы, и дублирование кода будет происходить быстро. Например, в метках и кнопках метод DrawText () происходит из интерфейса ITextHolder или в каждом классе, полученном из управления дочерними элементами IContainer.
Мое решение этой проблемы состоит в том, чтобы реализовать эти «дублированные» функции в выделенных адаптерах и переадресовывать вызовы к ним. Таким образом, и Label, и Button будут иметь элемент TextHolderAdapter, который будет вызываться внутри методов, унаследованных от интерфейса ITextHolder.
Я думаю, что этот дизайн должен оградить меня от необходимости иметь много общих функций в базовом классе, которые могут быстро раздуться с помощью виртуальных методов и ненужного «шумового кода». Изменения в поведении будут реализованы за счет расширения адаптеров, а не производных от Control классов.
Я думаю, что это называется «Стратегия», и, хотя на эту тему существуют миллионы вопросов и ответов, я хотел бы спросить вас о вашем мнении относительно того, что я принимаю во внимание для этого дизайна, и какие недостатки вы можете вспомнить в мой подход.
Я должен добавить, что есть почти 100% вероятность того, что будущие требования потребуют новых классов и новых функциональных возможностей.
IChild
кажется ужасным именем.
System.ComponentModel.Component
или ,System.Windows.Forms.Control
или любой из других существующих базовых классов? Зачем вам нужно создавать собственную иерархию управления и заново определять все эти функции с нуля?