Часто встречается ситуация, когда один пакет определяет интерфейс, который может быть реализован многими другими пакетами, как это показано на рис. 7.4. В данном случае отношение реализации означает, что шлюз базы данных (Database Gateway) определяет интерфейс, а другие классы шлюзов обеспечивают реализацию. На практике это может означать, что пакет шлюза базы данных (Database Gateway) содержит интерфейсы и абстрактные классы, которые полностью реализуются в других пакетах.
Общепринято размещать интерфейс и его реализацию в разных пакетах. Действительно, клиентский пакет часто содержит интерфейс, который должен быть реализован другим пакетом (такую же нотацию затребованного интерфейса я обсуждал на стр. 97).
Допустим, что вы хотите предоставить некоторый пользовательский интерфейс (UI) выключателей (controls) для включения и выключения некоторого объекта. Мы хотим, чтобы он работал с различными устройствами, такими как обогреватели (heaters) или лампы (lights). Выключатели UI должны вызывать методы обогревателя, но мы не хотим, чтобы выключатели зависели от обогревателя. Мы можем избежать этой зависимости, определяя в пакете выключателей интерфейс
|
|
который затем реализуется каждым классом, работающим с этими выключателями, как показано на рис. 7.5. Здесь представлен пример шаблона Separated Interface (Разделенный интерфейс) [19].
Когда применяются диаграммы пакетов
Я считаю, что диаграммы пакетов исключительно удобны в больших по размерам системах для представления картины зависимостей между основными элементами системы. Такие диаграммы хорошо соответствуют общепринятым программным структурам. Рисование диаграмм пакетов и зависимостей помогает держать под контролем зависимости приложения. Диаграммы пакетов представляют группирующий механизм времени компиляции. Для представления компоновки объектов во время выполнения применяются диаграммы составных структур (composite structure) (стр. 155).