
- •Основы uml
- •Введение
- •Введение в uml
- •1.1. История uml
- •1.2. Case-средства
- •1.3. Основные понятия объектно-ориентированного анализа и проектирования информационных систем
- •1.4. Общая характеристика моделей объектно-ориентированного анализа и проектирования
- •Основные элементы языка uml
- •2.1. Пакеты
- •2.2. Канонические диаграммы языка uml
- •2.3. Диаграмма вариантов использования (Use Case Diagram)
- •2.4. Диаграмма классов (Class Diagram)
- •2.5. Диаграмма кооперации (сотрудничества) (Collaboration Diagram)
- •2.6. Диаграмма последовательности (Sequence Diagram)
- •2.7. Диаграмма состояний (Statechart Diagram)
- •2.8. Диаграмма деятельности (Activity Diagram)
- •2.9. Диаграмма компонентов (Component Diagram)
- •2.10. Диаграмма размещения (Deployment Diagram)
- •Паттерны (Patterns)
- •3.1. Паттерны, их классификация
- •3.2. Паттерны проектирования
- •3.3. Архитектурные паттерны
- •Заключение
- •Литература
- •Пример разработки
3.3. Архитектурные паттерны
Наиболее известными архитектурными паттернами являются паттерны GRASP.
GRASP (General Responsibility Assignment Software Patterns) – общие паттерны распределения обязанностей в программных системах (обязанности описывают поведение объекта).
Паттерн Expert
Решение: назначить обязанность информационному эксперту – классу, у которого имеется информация, требуемая для выполнения обязанности.
Выполняется распределение обязанностей между классами.
Принцип: обязанности связываются с тем объектом, который имеет информацию, необходимую для их выполнения.
Пример: В приложении системы розничной торговли некоторому классу необходимо знать общую сумму продажи.
Согласно паттерну Expert нужно определить, объекты каких классов содержат информацию, необходимую для вычисления общей суммы. Фрагмент концептуальной модели приведен на рис. 3.8.
Рис. 3.92. Фрагмент концептуальной модели
Необходимо узнать стоимость всех проданных товаров SalesLineItem и просуммировать эти промежуточные суммы. Такой информацией обладает экземпляр объекта Sale. С точки зрения паттерна Expert объект Sale подходит для выполнения этой обязанности, т.е. является информационным экспертом.
Для вычисления промежуточной суммы элементов продажи необходимы значения SalesLineItem.quantity и ProductSpecification.price. Объекту SalesLineItem известно количество товара и связанный с ним объект ProductSpecification. В соответствии с паттерном Expert промежуточную сумму должен вычислять объект SalesLineItem, он и будет являться информационным экспертом. Это означает, что объект Sale должен передать сообщения subtotal() каждому объекту SalesLineItem, а затем просуммировать полученные результаты.
Для выполнения обязанности, связанной со знанием и предоставлением промежуточной суммы, объекту SalesLineItem должна быть известна стоимость товара. В данном случае информационным экспертом будет объект ProductSpecification.
Диаграмма кооперации для вычисления общей суммы приведена на рис. 3.9.
Таким образом, для выполнения обязанности знать и предоставлять общую сумму продажи были присвоены следующие обязанности:
Классу Sale обязанность total() – знание промежуточной суммы для данного товара;
Классу SalesLineItem обязанность subtotal() – знание общей суммы продажи;
Классу ProductSpecification обязанность price() – знание стоимости товара.
Рис. 3.93. Диаграмма кооперации для вычисления общей суммы
Паттерн Creator
Решение: Назначить классу B обязанность создавать экземпляры класса A, если выполняется одно из условий:
Класс B агрегирует объекты класса A;
Класс B содержит объекты класса A;
Класс B записывает экземпляры объектов класса A;
Класс B активно использует объекты класса A;
Класс B обладает данными инициализации, которые будут передаваться объектам класса A при его создании (при создании объектов А класс В является экспертом).
Класс В – создатель (creator) объектов класса А.
Если выполняется несколько из этих условий, то лучше использовать класс В, агрегирующий или содержащий класс А.
Выполняется распределение обязанностей, связанных с процессом создания объектов.
Пример: Чтобы найти класс, отвечающий за создание нового экземпляра объекта SalesLineItem в соответствии с паттерном Creator, необходимо найти класс, агрегирующий, содержащий и т.д. экземпляры объектов SalesLineItem. Рассмотрим концептуальную модель, представленную на рис. 3.8.
Так как объект Sale содержит (фактически – агрегирует) несколько объектов SalesLineItem, то его можно считать кандидатом для выполнения обязанности, связанной с созданием экземпляров объектов SalesLineItem. Это приводит к необходимости создания взаимодействия объектов, представленного на рис. 3.10.
Рис. 3.94. Создание экземпляров объекта SalesLineItem
Необходимо, чтобы в объекте Sale был определен метод makeLineItem.
Предположим, что при создании экземпляра объекта Payment нужно выполнить инициализацию с использованием общей суммы, содержащейся в объекте Sale. Так как объекту Sale эта сумма известна, то он и является кандидатом на выполнение обязанности, связанной с созданием экземпляра объекта Payment.
Паттерн Low Coupling
Решение: распределить обязанности таким образом, чтобы степень сцепления оставалась низкой.
Высокое сцепление приводит к возникновению проблем:
Изменения в классах приводят к локальным изменениям в других классах;
Затрудняется понимание каждого класса в отдельности;
Усложняется повторное использование классов.
Паттерн Low Coupling подразумевает такое распределение обязанностей, которое не влечет за собой чрезмерное повышение степени сцепления. Данный паттерн не рассматривается отдельно от других принципов, сформулированных в паттернах Expert и High Cohesion.
Пример: Пусть имеется три класса для терминального приложения системы розничной торговли: Sale (Продажа), POST (Торговая точка POST), Payment (Платеж). Предположим, что необходимо создать экземпляр класса Payment и связать его с объектом Sale. Так как в реальной предметной области регистрация объекта Payment выполняется объектом POST, то в соответствии с паттерном Creator объект POST является кандидатом для создания объекта Payment. Затем экземпляр объекта POST должен передать сообщение addPayment объекту Sale, указав в качестве параметра новый объект Payment (рис. 3.11). При таком распределении обязанностей предполагается, что класс POST связывается с данными класса Payment.
Рис. 3.95. Создание нового объекта Payment объектом POST
Альтернативный способ создания объекта Payment приведен на рис. 3.12.
Рис. 3.96. Создание нового объекта Payment объектом Sale
В обоих случаях предполагается, что в конечном итоге объекту Sale должно быть известно о существовании объекта Payment. С точки зрения числа связей между объектами второй из способов предпочтительнее, так как степень сцепления объектов в данном случае ниже (в первом случае добавляется новая связь).
Паттерн High Cohesion
Решение: распределение обязанностей, поддерживающее высокую степень связности.
Низкая степень связности приводит к проблемам:
Трудность понимания;
Сложность повторного использования;
Сложность поддержки;
Ненадежность, постоянная подверженность изменениям.
Данный паттерн не рассматривается отдельно от других принципов, сформулированных в паттернах Expert и Low Coupling.
Пример: Рассмотрим тот же пример, что и в случае с Low Coupling.
Предположим, что необходимо создать экземпляр класса Payment и связать его с текущей продажей. Так как в реальной предметной области сведения о платежах записываются в системе POST, то в соответствии с паттерном Creator объект POST является кандидатом для создания объекта Payment. Тогда экземпляр объекта POST сможет отправить сообщение addPayment объекту Sale, передавая в качестве параметра новый экземпляр объекта Payment (рис. 3.11). При таком распределении обязанностей платежи выполняет объект POST, т.е. он частично несет ответственность за выполнение системной операции addPayment. В данном обособленном примере это приемлемо, но если далее возлагать на класс POST обязанности по выполнению все новых и новых обязанностей, связанных с другими системными операциями, то этот класс будет слишком перегружен и будет обладать низкой степенью связности.
В другом варианте распределения обязанностей (рис. 3.12) функция создания экземпляра платежа делегирована объекту Sale. Благодаря чему поддерживается более высокая степень связности объекта POST.
Паттерн Controller
Решение: делегирование обязанностей по обработке системных сообщений классу, удовлетворяющему одному из следующих условий:
Класс представляет всю систему в целом (внешний контроллер);
Класс представляет всю организацию (внешний контроллер);
Класс представляет активный объект из реального мира (например, роль человека), который может участвовать в решении задачи (контроллер роли);
Класс представляет искусственный обработчик всех системных событий некоторого варианта использования и обычно называется обработчиком (handler) (контроллер варианта использования). Для всех системных событий в рамках одного варианта использования применяется один и тот же контроллер. Для каждого варианта использования должен быть свой контроллер.
Системное событие – событие высокого уровня, генерируемое внешним исполнителем. Пример системного события – когда кассир нажимает кнопку End Sale, он генерирует системное событие, свидетельствующее о завершении торговой операции.
Контроллер – объект, не относящийся к интерфейсу пользователя и отвечающий за обработку системных событий. Контроллер определяет методы для выполнения системных операций.
В приложении розничной торговли можно выделить несколько системных операций: endSale(), enterItem(), makePayment(). Какой класс можно выбрать в качестве контроллера?
Согласно паттерну Controller возможны следующие варианты:
POST (Торговая точка, оснащенная системой POST) – класс, представляющий всю систему в целом;
Store (Магазин) – класс, представляющий всю организацию;
Cashier (Кассир) – класс, представляющий активный объект из реального мира, который может участвовать в решении задачи;
BuyItemHandler – класс, представляющий искусственный обработчик всех системных событий некоторого варианта использования.
Выбор наиболее подходящего контроллера определяется факторами связности и сцепления. Системные операции присваиваются одному или нескольким классам контроллеров, например, POST.
Контрольные вопросы
Для чего предназначены архитектурные паттерны?
Какие архитектурные паттерны наиболее известны?
Для решения какой задачи предназначен паттерн Expert?
Для решения какой задачи предназначен паттерн Creator?
Для решения каких задач предназначены паттерны Low Coupling и High Cohesion?
Для чего используется паттерн Controller?