Всегда ли нужно создавать новые классы?
Начнем с вопроса, казалось бы, не имеющего никакого отношения к рассматриваемому вопросу, а именно - всегда ли нужно создавать новый класс для каждой новой задачи? Правильный ответ, конечно же, "нет". Это было бы странно и неэффективно. Могут быть ситуации, когда существующие классы по каким-либо причинам не устраивают архитектора, и тогда требуется создать новый класс. Следует, однако, избегать ситуаций, когда созданный класс (а точнее, его набор операций и атрибутов) практически повторяет существующий, лишь незначительно отличаясь от него. В общем случае, сказанное выше можно проиллюстрировать такой диаграммой (рис. 5):
Рисунок 5 - Иллюстрация примера
В дополнение можно назвать несколько причин, почему стоит использовать уже существующие классы:
Во-первых, идя этим путем, мы пользуемся плодами ранее принятых решений. Действительно, если когда-то мы уже решили некоторую проблему, зачем начинать все "с нуля", повторяя уже однажды проделанные действия?
Во-вторых, таким образом, мы делаем решение мобильным и расширяемым. Используя уже существующие классы и создавая на их основе новые, мы можем развивать решение практически неограниченно, добавляя лишь необходимые нам в данный момент детали - атрибуты и операции.
В-третьих, существующие классы, как правило, хорошо отлажены и показали себя в работе. Разработчику не надо тратить время на кодирование, отладку, тестирование и т. д., - мы работаем с хорошо отлаженным и проверенным временем кодом, который зарекомендовал себя в других проектах и в котором уже выявлено и исправлено большинство ошибок.
|
|
Понятия обобщения или генерализациииграют очень важную роль в ООП, являясь одним из его базовых принципов.
Обобщение – это отношение между более общей сущностью, называемой суперклассом, и ее конкретным воплощением, называемым подклассом. Иногда обобщение называют отношениями типа "является", имея в виду, что одни сущности (например, круг, квадрат, треугольник) являются воплощением более общей сущности (например, класса "геометрическая фигура"). При этом все атрибуты и операции суперкласса независимо от модификаторов видимости входят в состав подкласса.
Обобщение (или, как часто говорят, наследование) на диаграммах обозначается очень просто - незакрашенной треугольной стрелкой, направленной на суперкласс (рис. 6).
Для того чтобы научиться эффективно моделировать наследование, обратимся к классикам, а именно к Г. Бучу. Он советует проводить эту процедуру в такой последовательности:
1. Найдите атрибуты, операции и обязанности, общие для двух или более классов из данной совокупности. Это позволит избежать ненужного дублирования структуры и функциональности объектов.
|
|
2. Вынесите эти элементы в некоторый общий суперкласс, а если такого не существует, то создайте новый класс.
3. Отметьте в модели, что подклассы наследуются от суперкласса, установив между ними отношение обобщения.
Рисунок 6 – Обозначение обобщения
А вот и пример применения этого подхода (рис. 7):
Рисунок 7 – Пример применения обобщения
Объекты разной природы (или говоря проще, разных классов) могут поддерживать один и тот же интерфейс именно так, как того ожидает пользователь. Примером тому может служить рассмотренная выше диаграмма с геометрическими фигурами. Все рассмотренные фигуры имеют, например, операцию рисования на экране. С точки зрения пользователя в каждом случае это одно и то же действие. Однако реализованы эти операции по-разному - ведь процедура изображения прямоугольника сильно отличается от подобной процедуры для круга. Но для пользователя это неважно: ведь сигнатура-то одна и та же. А возможно это благодаря еще одному из основных принципов ООП - полиморфизму. Как мы только что упомянули, работа механизма полиморфизма основана на совпадении сигнатуры метода, объявленного в интерфейсе, и сигнатуры самого метода. Методы внутри классов-потомков могут быть (и наверняка будут!) переопределены, их реализации будут различными, а сигнатуры останутся неизменными. Таким образом (и в этом легко ощутить мощь ООП), выполняя одни и те же операции, разные объекты могут вести себя по-разному.
|
|
Полиморфизм является основой для реализации механизма интерфейсов в языках программирования. Как только пользователь обращается к некоторой операции через интерфейс, определяется фактический класс объекта и вызывается соответствующая операция класса. Примеры полиморфизма можно увидеть в самых обыденных вещах, которыми мы пользуемся в повседневной жизни. Оглянитесь вокруг - мир построен по ООП, Например, всем привычная кредитная карточка, является интерфейсом для доступа к банковскому счету через банкомат (и не только), одинаково работает в любой стране, вот только ведет себя чуть-чуть по-разному, т. к. банкомат выдает деньги в местной валюте. Пример не очень корректный, но зато очень наглядный.
Инкапсуляция, наследование и полиморфизм, с которыми мы только что познакомились, являются теми самыми тремя китами, на которых держится ООП. Если вы поняли суть этих базовых принципов и осознали их истинную мощь, вы прошли большую часть пути, ведущего к полному овладению ООП как наиболее адекватной методикой описания (так и тянет сказать "проектирования") окружающего нас мира.
|
|
Отношения между классами
Ни один из объектов окружающего нас мира не существует сам по себе. Птицы летают потому, что есть воздух, на который опираются их крылья. Каждый из нас связан с массой других людей разнообразными родственными, профессиональными и другими связями, предполагающими различные типы отношений. Точно так же и классы связаны между собой. И чтобы в полной мере овладеть ООП, нам необходимо понять суть этих отношений и научиться их идентифицировать.
Мы сказали, что объекты находятся в определенных отношениях друг с другом. Один из типов таких отношений – это зависимость. Думаем, суть такого отношения понятна уже из его названия - зависимость возникает тогда, когда реализация класса одного объекта зависит от спецификации операций класса другого объекта. И если изменится спецификация операций этого класса, нам неминуемо придется вносить изменения и в зависимый класс. Приведем простой пример, опять-таки взятый из нашей повседневности. Иногда к нам в руки попадают видеофайлы, воспроизвести которые "с лету" не удается. Почему? Правильно, потому что на компьютере не установлены соответствующие кодеки. То есть операция "Воспроизведение", реализуемая программой-медиаплеером, зависит от операции "Декомпрессия", реализуемой кодеком. Если спецификация операции"Декомпрессия" изменится, придется менять код медиаплеера, иначе он просто не сможет работать с каким-то кодеком и, в лучшем случае, завершит свою работу с ошибкой. А вот так зависимость между классами изображается в UML (рис. 8):
Рисунок 8 – Изображение зависимости между классами
Стоит отметить, что зависимости на диаграммах изображают далеко не всегда, а только в тех случаях, когда их отображение является важным для понимания модели. Часто зависимости лишь подразумеваются, т. к. логически следуют из природы классов.
Другой вид отношений между объектами - это ассоциация. Это просто связь между объектами, по которой можно между ними перемещаться. Ассоциация может иметь имя, показывающее природу отношений между объектами, при этом в имени может указываться направление чтения связи при помощи треугольного маркера. Однонаправленная ассоциация может изображаться стрелкой. Проиллюстрируем сказанное примерами (рис. 9):
Рисунок 9 – Пример изображения однонаправленной ассоциации
Кроме направления ассоциации, мы можем указать на диаграмме роли, которые каждый класс играет в данном отношении, икратность, то есть количество объектов, связанных отношением (рис. 10):
Рисунок 10 – Пример изображения кратности
И насчет ролей, и насчет кратности на этой диаграмме все понятно - человек может вообще не работать, работать в одной или более компаниях, а вот компании в любом случае нужен хотя бы один сотрудник. Кстати, о кратности. Ассоциация может объединять три и более класса. В этом случае она называется n-арной и изображается ромбом на пересечении линий, как показано на этой диаграмме, позаимствованной нами из ZicomMentor(рис. 11):
Рисунок 11 – Пример изображения n-арной ассоциации
Ранее мы говорили, что ассоциация - это "просто связь" между объектами. На самом деле, в реальности связи бывают "просто связями" крайне редко. Обычно при ближайшем рассмотрении под ассоциацией понимается более сложное отношение между классами, например, связь типа "часть-целое". Такой вид ассоциации называется ассоциацией с агрегированием. В этом случае один класс имеет более высокий статус (целое) и состоит из низших по статусу классов (частей). При этом выделяют простое и композитное агрегирование и говорят о собственно агрегации и композиции. Простая агрегация предполагает, что части, отделенные от целого, могут продолжать свое существование независимо от него. Под композитным же агрегированием понимается ситуация, когда целое владеет своими частями и их время жизни соответствует времени жизни целого, т. е. независимо от целого части существовать не могут. Примеры этих видов ассоциаций и их обозначений в UML можно увидеть на следующей диаграмме (рис. 12).
Рисунок 12 – Пример изображения агрегации и композиции
Винчестер можно вынуть из компьютера и установить в новый компьютерили в USB-карман, т. е. существование жесткого диска с разборкой системного блока не заканчивается. А вот кнопки без окон обычно существовать не могут - с закрытием окна кнопки также исчезают.
И, наконец, еще одна важная вещь, касающаяся ассоциации. В отношении между двумя классами сама ассоциация тоже может иметь свойства и, следовательно, тоже может быть представлена в виде класса. Пример (рис. 13):
Рисунок 13 – Пример представления ассоциации в виде класса
Действительно, перед началом трудовых отношений работник и работодатель подписывают между собой контракт, который имеет такие атрибуты, как, например, описание работ, сроки их выполнения, порядок оплаты и т. д.
А вот более сложный, но, опять-таки, взятый из реальной жизни пример моделирования отношений между классами, позаимствованный нами из ZicomMentor(рис. 14):
Рисунок 14 – Пример моделирования отношений между классами
И наконец, доказательство того, что UML можно использовать для чего угодно, в том числе и для записи сказок: диаграмма, описывающая предметную область сказки о Курочке Рябе и взятая с сайта конкурса шуток на UML (http://www.umljokes.com/) (рис. 15):
Рисунок 15 –Моделирования отношений между классами на примере сказки
Выводы
· Инкапсуляция защищает внутреннее устройство объекта и реализуется путем ограничения доступа к атрибутам и операциям класса из других частей программы.
· Обобщение позволяет повторно использовать уже существующие решения, создавая новые классы путем наследования от имеющихся классов.
· Полиморфизм позволяет работать с группой разнородных объектов одинаковым образом, не задумываясь о различиях в реализации.
· Инкапсуляция, наследование и полиморфизм - три кита, на которых держится ООП.
· В любой системе между объектами существуют отношения разных типов.
· Отношение зависимости означает, что реализация одного класса зависит от спецификации операций другого класса.
· Ассоциация выражает отношение между несколькими равноправными объектами и может иметь направление, роли и кратность, а также изображаться в виде класса ассоциации.
· Композиция и агрегация используются, если между объектами существуют отношения типа "часть-целое", причем композиция предполагает, что части не могут существовать отдельно от целого.
Порядок выполнения работы
1. Изучить теоретический материал. Выполнить примеры
2. Согласно заданному варианту, выполнить проектирование системы:
- создать иерархию классов системы;
- для классов указать стереотипы;
- разместить классы по пакетам в Designmodel, как это описано в методичке (придерживаться принципа: количество связей внутри пакета больше количества связей, проходящих за границы пакета);
- связать объекты на диаграммах взаимодействия с классами, а сообщения – с операциями;
- каждый класс снабдить описанием, которое должно включать в себя краткое описание (ответственность класса), описание атрибутов в виде таблицы (имя, описание, тип), таблицу с описанием операций (имя, описание, сигнатура);
- построить диаграммы классов системы, отображающие связи между классами;
- для описания поведения экземпляров отдельных классов построить диаграммы состояний;
- построить диаграммы деятельности для моделирования сложных операций (с альтернативами, циклами);
Контрольные вопросы
- Какие три принципа лежат в основе ООП?
- Что такое интерфейс? На каком из базовых принципов ООП основан механизм интерфейсов?
- Что такое n-арная ассоциация?
- В чем разница между агрегацией и композицией?
- Что такое класс ассоциации?
Лабораторная работа №№12-13
Дата добавления: 2020-04-25; просмотров: 147; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!