Во-первых, контекст: Мы разрабатываем некоторые приложения, используя QP Framework от квантовых скачков. QP — это, по сути, менеджер событий для конечных автоматов.
Наш подход: Поскольку мы используем QP, наши модули взаимодействуют с событиями и сигналами (классами/структурами и перечислениями), за исключением некоторых очень специфических модулей, которые взаимодействуют с помощью методов.
Проблема: Для этих последних модулей интерфейсы просты, просто набор всех общедоступных методов в указанном модуле, однако как насчет других? Можем ли мы сказать, что интерфейс — это композиция других классов и перечислений?
Поскольку модули взаимодействуют, отправляя/принимая события, оба должны знать, какие пакеты данных (события) могут проходить через этот интерфейс.
Можем ли мы представить такой интерфейс? или интерфейс должен быть только набором методов?
редактировать 1:
Отвечая на комментарии ниже, я не хочу сказать, что в интерфейсе есть вложенные классы, но что интерфейс будет определять указанные классы, чтобы их можно было использовать как события, но, судя по вашим ответам, использование signals
было бы лучшим подходом. (Префикс ADC:: и имя интерфейса не одно и то же, просто несколько неудачных вариантов именования, поскольку имя пакета было ADC, как и интерфейс)
редактировать 2:
Судя по комментариям и ответам ниже, я ничего не знал о стереотипе signal
, поэтому, обновляя вопрос, я думаю, что он станет чем-то вроде этого?
Это решает проблему классов и сигналов, однако enum
остается...
Мое намерение состояло в том, чтобы сказать, что интерфейс будет определять эти ключевые слова, то есть модуль, который реализует интерфейс, должен определить это enum
и их значения.
Это правильный подход?
Для обозначения вложенных классов см. stackoverflow.com/questions/27797531/…
Интерфейс на вашей диаграмме совершенно законен. Интерфейсы UML не имеют ограничений интерфейсов Java: они могут иметь операции, атрибуты, и всевозможные ассоциации (кстати, агрегация формально не добавляет никакой семантики к ассоциациям, и вы можете смело рассмотреть возможность удаления белых ромбов ), включая состав (черный ромб).
Однако это может не соответствовать тому, что вы ищете: интерфейсы выражают контракт. Это означает, что классы, реализующие его, должны предоставлять эти атрибуты и ассоциации, а не то, что классы получат все эти функции путем своего рода «наследования».
Более того, я не уверен, пытаетесь ли вы выразить какой-то сложный интерфейс или просто не нашли лучшего способа представить потребление/генерацию событий. В последнем случае это был бы чрезмерно сложный и вводящий в заблуждение подход.
Для дизайна, основанного на событиях, вам может быть интересно использовать сигналы. Сигналы похожи на классы, но есть элементы UML для выражения способности обрабатывать семейство событий и/или генерировать события. Более того, это облегчает связь между диаграммами последовательности и диаграммами классов, поскольку сообщение может напрямую соответствовать экземпляру события.
Спасибо, и да, сигналы кажутся лучшим подходом к этому, я отредактировал свой вопрос с новым подходом.
@EduardoRodrigues относительно редактирования 2, подход к перечислениям неверен. Там написано, что интерфейс агрегирован с перечислениями. Вы могли бы сказать, что интерфейс предоставляет перечисления путем их вложения. Но нельзя сказать, что реализация интерфейса должна определять перечисления. Более того, если перечисления и их литералы уже известны до такой степени, что вы можете сказать, что интерфейс должен определять их таким образом... это означает, что они уже определены до реализации интерфейса. Единственный способ избежать этого - сделать интерфейс параметризованным интерфейсом с...
два типа в качестве параметров и определить ограничения на тот факт, что эти типы должны быть перечислением, а литеральные имена должны быть определены. Но это звучит довольно громоздко. Более простой способ — добавить в схему комментарии, поясняющие этот принцип в неформальной форме, без использования шаблонов.
QPFramework работает, отправляя сигналы между конечными автоматами, поэтому все они должны быть уникальными и известными обеим сторонам интерфейса. Мои мысли заключались в том, чтобы сказать, что тот, кто использует интерфейс, может посылать эти «сигналы», а тот, кто их реализует, должен иметь возможность их получать. В этом случае каждый сигнал связан с событием (сигналом UML), поэтому я мог бы прокомментировать их, сказав, что каждое событие должно объявлять соответствующий сигнал, но это не всегда так. Как лучше всего сказать, что для реализации этого интерфейса эти литералы должны быть определены? Должен ли сам интерфейс определять их?
Сама по себе модель нормальная. Однако, скорее всего, это не то, что вы хотели. Общая агрегация не имеет определенного значения. См. стр. 110 UML 2.5
общий | Указывает, что свойство имеет общую семантику агрегирования. Точная семантика разделяемой агрегации зависит от области приложения и разработчика моделей.
Поэтому, если вы не определите их значение, модель не имеет определенного значения.
Если вы намереваетесь наследовать операции/атрибуты, вы должны нарисовать открытую треугольную стрелку в сторону других классов. Перечисления должны быть просто атрибутом (простая ассоциация с ролью).
P.S. Согласно комментарию Герта, я тоже замечаю вложенность. Таким образом, вы явно переопределяете это, добавляя (бессмысленную) общую агрегацию. Вы можете представить вложенные классы, показав их внутри увеличенного «интерфейса». Или вы используете (как предложил Герт) отношение вложенности (лично я использую это редко, но это альтернатива).
Из префикса ADC:: я понимаю, что на самом деле это классы, вложенные (и принадлежащие) этому интерфейсу ADC? Если это так, вы должны сделать это более ясным, также показав вложенность классов в браузере проекта. Если вы хотите визуализировать вложенность на диаграмме, вы можете использовать отношение вложенности. (конец которого выглядит как круг со знаком + внутри.)