Джим Арлоу, Айла Нейштадт - UML 2 и Унифицированный процесс. Практический объектно-ориентированный анализ и проектирование (1037782), страница 77
Текст из файла (страница 77)
9.44 [Jacobson 1] с разрешения издательства Addison+Wesley19.3. Что такое интерфейс?Интерфейс определяет именованный набор открытых свойств.Интерфейс определяет именованный набор открытых свойств.Главная идея, лежащая в основе интерфейсов, – разделение описанияфункциональности (интерфейс) от ее реализации классификатором, таким как класс или подсистема. Создать экземпляр интерфейса невозможно.
Он просто объявляет контракт, который может быть реализованклассификаторами. Все, что реализует интерфейс, принимает и соглашается следовать определяемому интерфейсом контракту.Интерфейсы разделяют описание функциональности от ее реализации.Возможности, которые могут быть описаны в интерфейсах, перечислены в табл. 19.1. В ней также показаны обязанности реализующих ихклассификаторов по отношению к интерфейсу.В интерфейсах также должны присутствовать описания семантики ихвозможностей (обычно в виде текста или псевдокода) как руководствадля тех, кто будет их реализовывать.422Глава 19. Интерфейсы и компонентыТаблица 19.1Интерфейс описываетРеализующий классификаторОперацияДолжен иметь операцию с аналогичной сигнатуройи семантикой.АтрибутДолжен иметь открытые операции для задания и получения значения атрибута – не требуется, чтобы уреализующего классификатора на самом деле былатрибут, определенный интерфейсом, но его поведение должно быть таким, как будто он существует.АссоциацияДолжен иметь ассоциацию с целевым классификатором – если интерфейс описывает ассоциацию сдругим интерфейсом, классификатор, реализующий эти интерфейсы, должен реализовывать ассоциацию между ними.ОграничениеДолжен поддерживать ограничение.СтереотипИмеет стереотип.Помеченное значениеИмеет помеченное значение.Протокол (например, оп Должен реализовывать протокол.ределенный конечнымавтоматом протокола –см.
раздел 21.2.1)Атрибуты и операции в интерфейсе должны быть полностью описаныи включать следующее:• полную сигнатуру операции (имя, типы всех параметров и возвращаемый тип);• семантику операции – она может быть записана в виде текста илипсевдокода;• имена и типы атрибутов;• все стереотипы, ограничения или помеченные значения операцииили атрибута.Важно помнить, что интерфейс определяет только описание своих возможностей и что он никогда не заключает в себе какойлибо конкретной реализации.Интерфейсы определяют контракт.Интерфейсы могут иметь огромное влияние на способ проектирования.До сих пор проектирование заключалось в соединении определенныхклассов.
Этот процесс можно было бы назвать «проектирование реализации». Однако более гибким подходом является «проектированиеконтракта», когда классы соединяются с интерфейсом, после чего этотинтерфейс может быть реализован любым количеством классов и дру42319.4. Предоставляемые и требуемые интерфейсыгих классификаторов. Стандартные библиотеки Java являются свидетельством гибкости и мощи такого подхода. Часто говорят, что интерфейс определяет сервис, предлагаемый классом, подсистемой или компонентом. Современные программные архитектуры часто основываются на сервисах.Если язык реализации не поддерживает интерфейсы непосредственно,используйте абстрактные классы.Язык Java первым из широко используемых языков программирования ввел специальную языковую конструкцию для интерфейсов. Однако интерфейсы вполне могут использоваться при программировании на языках, не имеющих такой специальной конструкции.
Например, в С++ просто описывается полностью абстрактный класс, т. е. абстрактный класс, все операции которого абстрактны.19.4. Предоставляемые и требуемые интерфейсыРеализуемый классификатором набор интерфейсов называют предо+ставляемыми (provided) интерфейсами.Реализуемые классификаторами интерфейсы являются предоставляемыми интерфейсами.Интерфейсы, необходимые для работы классификатора, называюттребуемыми (required) интерфейсами.Необходимые классификатору интерфейсы – это требуемые интерфейсы.На рис. 19.3 показаны два варианта UMLсинтаксиса для предоставляемых интерфейсов: нотация в стиле «класса» (в которой можно по«interface»Borrowborrow()return()isOverdue()интерфейсBorrowотношениереализацииBookCDНотация в стиле «класса»BookCDНотация в стиле «леденец на палочках»(примечание: в этой краткой нотациинельзя показать операции или атрибуты)Рис.
19.3. Два варианта синтаксиса для предоставляемых интерфейсов424Глава 19. Интерфейсы и компонентыказывать атрибуты и операции) и краткая нотация в стиле «леденецна палочках» (в которой можно не показывать атрибуты и операции).Пример на рис. 19.3 взят из простой системы управления библиотекой,в которой класс обслуживает коллекцию объектов Book и коллекциюобъектов CD. Каждый объект Book и CD реализуют интерфейс Borrow, определяющий протокол для позиций, которые могут быть выданы навремя. Хотя семантически Book и CD совершенно разные, интерфейс Borrow позволяет Library рассматривать их одинаково, по крайней мерев том, что касается протокола выдачи книг во временное пользование.Обычно имена интерфейсов и классов совпадают; они записываютсяв стиле UpperCamelCase.
Однако в Visual Basic и C# действует общепринятый стандарт – имя каждого интерфейса начинается с большой I,например IBorrow. Другой стиль присваивания имен – добавление в конце имени суффикса «able», например Borrowable или IBorrowable.Отношение реализации – это отношение между описанием (в данномслучае интерфейсом) и тем, что реализует это описание (в данном случае классами Book и CD). Позже мы увидим, что не только классы могутреализовывать интерфейс. Это также могут делать и другие классификаторы, такие как пакеты и компоненты.Обратите внимание, что в нотации в стиле класса отношение реализации представляется в виде пунктирной линии с незаштрихованнойстрелкой, тогда как в нотации «леденец на палочках» это сплошнаялиния без стрелки. Главная причина в том, что нотация «леденец напалочках» должна оставаться максимально краткой.
Нотацию классаиспользуют, когда хотят показать возможности интерфейса, а нотацию «леденец на палочках» – когда этого делать не надо. Но они обепредставляют одно и то же.На рис. 19.4 показан класс Library, которому требуется интерфейс Borrow. Требуемый интерфейс можно показать как зависимость, направнотация в стиле классаLibrary«interface»Borrowнотация в стиле «леденец на палочках»LibraryLibraryBorrowпредпочтительнаяBorrowпредпочтительнаятребуемый интерфейсРис. 19.4.
Варианты синтаксиса требуемого интерфейса42519.4. Предоставляемые и требуемые интерфейсы11LibraryразъемсборкиBorrowBook0..*CD0..*Рис. 19.5. Система Library в сборкеленную к интерфейсу (как в нотации класса, так и в нотации «леденецна палочках»), или как гнездо под требуемый интерфейс. В любом случае эта нотация показывает, что Library понимает и требует конкретныйпротокол, определенный интерфейсом Borrow. Все элементы, реализующие этот интерфейс, потенциально могут быть подключены к Library,и Library поймет, что они могут быть выданы на время и возвращены.На рис. 19.5 система Library показана в сборке. Разъем сборки указывает, что и Book, и CD предоставляют необходимый Library набор сервисов(описанных классом Borrow).Другой хороший пример интерфейсов с множеством реализаций можно найти в классахколлекциях в стандартных библиотеках Java(рис.
19.6). Хотя там описано всего восемь интерфейсов, Java предоставляет множество разных реализаций, каждая из которых обладаетразличными характеристиками. При проектировании интерфейса Javaпроектировщик может перенести фактическую реализацию интерфейса на период реализации и позволить Javaпрограммисту выбиратьреализацию с наиболее подходящими характеристиками.IterableCollectionListMapSetSortedMapConcurrentMapSortedSetРис.
19.6. Интерфейсы с множеством реализаций в классах+коллекциях Java426Глава 19. Интерфейсы и компоненты19.5. Сравнение реализации интерфейсаи наследованияРеализация интерфейса – «реализует определяемый им контракт».Теперь стоит обсудить, в чем разница между реализацией интерфейсаи наследованием. Семантика реализации интерфейса – «реализует определенный контракт», а семантика наследования – «является».
Принцип замещаемости применим как к наследованию, так и к реализацииинтерфейса. Таким образом, оба типа отношений могут формироватьполиморфизм.Семантика наследования – «является».Чтобы проиллюстрировать разницу между реализацией интерфейсаи наследованием, мы предлагаем альтернативное решение для системы управления библиотекой на основании наследования (рис. 19.7).Оно кажется вполне приемлемым и в некотором отношении даже более простым, но здесь есть некоторые проблемы.Прежде всего обсудим, почему эта основанная на наследовании модельне совсем подходит. Здесь очень четко определяется, что объекты Bookи CD имеют тип BorrowableItem.