ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 16.03.2024
Просмотров: 95
Скачиваний: 0
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Соответственно, архитектурным решением может быть сделать общий абстрактный класс AbstractBook, в котором будут реализованы общие операции для всех сущностей, что находятся в библиотеке. От него будут наследоваться классы Book и Magazine. Но нельзя создать никаких экземпляров класса AbstractBook, а нам необходимо именно ими управлять в классе Library. Это решение не подходит, либо должно быть усовершенствовано.
Далее, для того, чтобы сделать возможным управление классаминаследниками AbstractBook, можно вынести методы из AbstractBook в интерфейс LibraryEntity. Абстрактный класс будет реализовывать этот интерфейс. Таким образом, Library сможет управлять объектами типа LibraryEntity. Например, станет возможным такой код.
LibraryEntity entity = new Book();
Почему такое возможно? Потому что абстрактный класс AbstractBook реализует интерфейс LibraryEntity, а класс Book наследует абстрактный класс AbstractBook. Язык Java позволяет присваивать интерфейсу ссылки на объекты тех классов, которые реализуют этот интерфейс.
Это решение и является подходящим для такой ситуации.
Соответственно, будут изменения и в классе Library, изменятся названия атрибутов, добавятся новые операции и изменятся старые. Дополнительно изменено имя свойства “numberInLibrary” на “ID”.
Если бы не было этапа проектирования, который сейчас и выполняется, то именно сейчас пришлось бы переписывать
огромное количество кода. Именно поэтому принцип “сначала спроектируй
потом пиши код” позволяет повысить эффективность. Сейчас изменить архитектуру, даже полностью её переписать, будет намного легче, чем переписать весь код, который её в будущем будет реализовывать.
Внесем все эти изменения в UMLкод.
@startuml
skinparam classAttributeIconSize 0
interface LibraryEntity {
+getID() : long
+getName() : String
}
abstract class AbstractBook {
ID : long
name : String
}
class Book {
ISBN : String
author : String [1..*]
year : int
}
class Magazine {
datePublication: LocalDate
publisher : String
}
class Library {
numberOfEntities : long
name : String
+findEntityByName(name : String) : LibraryEntity
+findEntityByID(id : long) : LibraryEntity
+addNewEntity(entity : LibraryEntity) : boolean
+deleteEntity(id : long) : boolean
}
LibraryEntity "0..*" <> "1" Library
LibraryEntity <|.. AbstractBook AbstractBook <| Book AbstractBook <| Magazine @enduml
Добавим комментарий к классу Magazine.
class Magazine {
datePublication: LocalDate
publisher : String
}
note right: LocalDate is from DateTime API in Java 8
Эта диаграмма классов только поверхностно охватила систему управления книгами, но этого вполне достаточно в качестве примера, как следует начинатьразрабатывать архитектуру приложений.
Безусловно, в этом примере можно сделать
еще много уточнений и усовершенствований, прежде чем на основе полученной архитектуры можно будет сделать рабочий проект.
Создадим в этом же проекте (модуле) файл диаграммы последовательностей.
Имя диаграммы: LibrarySequenceDiagram. Так как это диаграмма последовательности, то с помощью её мы сможем показать, какова же последовательность действий в проектируемой системе. Иначе говоря, что же будет делать система при наступлении той или иной ситуации?
Разработаем две диаграммы последовательности: одну для сценария нахождения чеголибо в библиотеке по его имени (name), вторую для сценария удаления чеголибо из библиотеки по идентификатору (ID).
ПолнуюинформациюоспецификацииPlantUMLдлядиаграммпоследовательностейможнопосмотреть в файле PlantUML_Language_Reference_Guide или по адресу http://plantuml.sourceforge.net/sequence.html.
Сценарийнахождениячего-либовбиблиотекепоимени
Сначала необходимо определить объекты, которые посылают друг другу сообщение (иначе говоря, вызывают или какимлибо образом используют друг друга). Когда в классе Library вызывается функция findEntityByName(), то эта функция будет брать список всех сущностей LibraryEntityList, хранящихся в библиотеке, и выполнять в нем поиск. Почему
этот список сущностей не был указан в атрибутах в диаграмме классов? Потому что этот список там представлен в виде двусторонней ассоциации. Поэтому имя этого списка будет в диаграмме последовательности, но не будет в диаграмме классов.
Функция findEntityByName() будет вызываться классомклиентом библиотеки LibraryClient, которого также не было на диаграмме классов. Таким образом, можно написать следующий код, отображающийся в UML.
@startuml
LibraryClient > Library : findEntityByName(name : String) Library > LibraryEntityList : getEntity
LibraryEntityList > Library: anEntity @enduml
В диаграмме происходит следующее: LibraryClient вызывает у Library метод findEntityByName, Library запрашивает у списка LibraryEntityList одну сущность, и эта сущность передается библиотеке.
Так как при поиске необходимого элемента в библиотеке происходит перебор всех элементов, то в диаграмме необходимо отобразить, что этот процесс происходит в цикле. Также нужно указать, что каждый раз после возврата элемента из списка происходит проверка на соответствие поисковой строке.
@startuml
LibraryClient > Library : findEntityByName(name : String) loop all entities in list
Library > LibraryEntityList : getEntity LibraryEntityList > Library : anEntity alt anEntity.name == name
Library > LibraryClient : anEntity
end end @enduml
Однако по такой диаграмме последовательности становится понятно, что в LibraryClient будут “возвращаться” много элементов библиотеки, если они будут подходить под поисковый запрос. Значит, необходимо возвращать результаты запроса не отдельными элементами (классуклиенту обрабатывать большое количество результатов неудобно), а отдельным классом ResultEntityList. Значит, каждый раз, когда полученный из списка anEntity будет удовлетворять запросу, он будет отправляться в ResultEntityList, а по завершении цикла, список результатов ResultEntityList будет возвращен клиенту LibraryClient.
@startuml
LibraryClient > Library : findEntityByName(name : String) loop all entities in list
Library > LibraryEntityList : getEntity LibraryEntityList > Library : anEntity alt anEntity.name == name
Library > ResultEntityList : anEntity
end end
ResultEntityList > LibraryClient : resultList @enduml
Сценарийудалениячего-либоизбиблиотекипоидентификатору
Клиент библиотеки посылает библиотеке запрос на удаление элемента из библиотеки. Класс библиотеки просматривает весь список своих элементов и ищет такой элемент, ID которого совпадает с запрашиваемым. Если такой элемент находится (используется фрейм alt), то из списка этот элемент удаляется, а клиенту возвращается значение true (элемент на самом деле удален). Если же в списке
Далее, для того, чтобы сделать возможным управление классаминаследниками AbstractBook, можно вынести методы из AbstractBook в интерфейс LibraryEntity. Абстрактный класс будет реализовывать этот интерфейс. Таким образом, Library сможет управлять объектами типа LibraryEntity. Например, станет возможным такой код.
LibraryEntity entity = new Book();
Почему такое возможно? Потому что абстрактный класс AbstractBook реализует интерфейс LibraryEntity, а класс Book наследует абстрактный класс AbstractBook. Язык Java позволяет присваивать интерфейсу ссылки на объекты тех классов, которые реализуют этот интерфейс.
Это решение и является подходящим для такой ситуации.
Соответственно, будут изменения и в классе Library, изменятся названия атрибутов, добавятся новые операции и изменятся старые. Дополнительно изменено имя свойства “numberInLibrary” на “ID”.
Если бы не было этапа проектирования, который сейчас и выполняется, то именно сейчас пришлось бы переписывать
огромное количество кода. Именно поэтому принцип “сначала спроектируй
потом пиши код” позволяет повысить эффективность. Сейчас изменить архитектуру, даже полностью её переписать, будет намного легче, чем переписать весь код, который её в будущем будет реализовывать.
Внесем все эти изменения в UMLкод.
@startuml
skinparam classAttributeIconSize 0
interface LibraryEntity {
+getID() : long
+getName() : String
}
abstract class AbstractBook {
ID : long
name : String
}
class Book {
ISBN : String
author : String [1..*]
year : int
}
class Magazine {
datePublication: LocalDate
publisher : String
}
class Library {
numberOfEntities : long
name : String
+findEntityByName(name : String) : LibraryEntity
+findEntityByID(id : long) : LibraryEntity
+addNewEntity(entity : LibraryEntity) : boolean
+deleteEntity(id : long) : boolean
}
LibraryEntity "0..*" <> "1" Library
LibraryEntity <|.. AbstractBook AbstractBook <| Book AbstractBook <| Magazine @enduml
Добавим комментарий к классу Magazine.
class Magazine {
datePublication: LocalDate
publisher : String
}
note right: LocalDate is from DateTime API in Java 8
Эта диаграмма классов только поверхностно охватила систему управления книгами, но этого вполне достаточно в качестве примера, как следует начинатьразрабатывать архитектуру приложений.
Безусловно, в этом примере можно сделать
еще много уточнений и усовершенствований, прежде чем на основе полученной архитектуры можно будет сделать рабочий проект.
Создание диаграммы последовательностей
Создадим в этом же проекте (модуле) файл диаграммы последовательностей.
Имя диаграммы: LibrarySequenceDiagram. Так как это диаграмма последовательности, то с помощью её мы сможем показать, какова же последовательность действий в проектируемой системе. Иначе говоря, что же будет делать система при наступлении той или иной ситуации?
Разработаем две диаграммы последовательности: одну для сценария нахождения чеголибо в библиотеке по его имени (name), вторую для сценария удаления чеголибо из библиотеки по идентификатору (ID).
ПолнуюинформациюоспецификацииPlantUMLдлядиаграммпоследовательностейможнопосмотреть в файле PlantUML_Language_Reference_Guide или по адресу http://plantuml.sourceforge.net/sequence.html.
Сценарийнахождениячего-либовбиблиотекепоимени
Сначала необходимо определить объекты, которые посылают друг другу сообщение (иначе говоря, вызывают или какимлибо образом используют друг друга). Когда в классе Library вызывается функция findEntityByName(), то эта функция будет брать список всех сущностей LibraryEntityList, хранящихся в библиотеке, и выполнять в нем поиск. Почему
этот список сущностей не был указан в атрибутах в диаграмме классов? Потому что этот список там представлен в виде двусторонней ассоциации. Поэтому имя этого списка будет в диаграмме последовательности, но не будет в диаграмме классов.
Функция findEntityByName() будет вызываться классомклиентом библиотеки LibraryClient, которого также не было на диаграмме классов. Таким образом, можно написать следующий код, отображающийся в UML.
@startuml
LibraryClient > Library : findEntityByName(name : String) Library > LibraryEntityList : getEntity
LibraryEntityList > Library: anEntity @enduml
В диаграмме происходит следующее: LibraryClient вызывает у Library метод findEntityByName, Library запрашивает у списка LibraryEntityList одну сущность, и эта сущность передается библиотеке.
Так как при поиске необходимого элемента в библиотеке происходит перебор всех элементов, то в диаграмме необходимо отобразить, что этот процесс происходит в цикле. Также нужно указать, что каждый раз после возврата элемента из списка происходит проверка на соответствие поисковой строке.
@startuml
LibraryClient > Library : findEntityByName(name : String) loop all entities in list
Library > LibraryEntityList : getEntity LibraryEntityList > Library : anEntity alt anEntity.name == name
Library > LibraryClient : anEntity
end end @enduml
Однако по такой диаграмме последовательности становится понятно, что в LibraryClient будут “возвращаться” много элементов библиотеки, если они будут подходить под поисковый запрос. Значит, необходимо возвращать результаты запроса не отдельными элементами (классуклиенту обрабатывать большое количество результатов неудобно), а отдельным классом ResultEntityList. Значит, каждый раз, когда полученный из списка anEntity будет удовлетворять запросу, он будет отправляться в ResultEntityList, а по завершении цикла, список результатов ResultEntityList будет возвращен клиенту LibraryClient.
@startuml
LibraryClient > Library : findEntityByName(name : String) loop all entities in list
Library > LibraryEntityList : getEntity LibraryEntityList > Library : anEntity alt anEntity.name == name
Library > ResultEntityList : anEntity
end end
ResultEntityList > LibraryClient : resultList @enduml
Сценарийудалениячего-либоизбиблиотекипоидентификатору
Клиент библиотеки посылает библиотеке запрос на удаление элемента из библиотеки. Класс библиотеки просматривает весь список своих элементов и ищет такой элемент, ID которого совпадает с запрашиваемым. Если такой элемент находится (используется фрейм alt), то из списка этот элемент удаляется, а клиенту возвращается значение true (элемент на самом деле удален). Если же в списке