Lecture
Это окончание невероятной информации про паттерны поведения.
...
objects;
Structure
Figure 2.41 Command Pattern Structure
In the following diagram (Fig. 2.42), you can see how the Command breaks the connection between the initiator and the recipient (as well as the request that the latter must fulfill).
Title
High Cohesion (weak gearing)
Problem
In terms of object-oriented design, cohesion (or, more precisely, functional gearing) is a measure of coherence and focus of class duties. An element is considered to have a high degree of engagement if its duties are closely related to each other and it does not perform exorbitant amounts of work.
Figure 2.42 Command Pattern. Object Interaction
In the role of such elements may be classes, subsystems, etc. A class with a low degree of engagement performs many disparate functions or unrelated duties. It is undesirable to create such classes because they lead to the following problems.
Classes with a weak link are usually too “abstract” or perform duties that can be easily distributed among other objects.
Decision
Distribution of duties, maintaining a high degree of engagement.
results
Example
To analyze the High Cohesion pattern, you can use the same example as for Low Coupling. Suppose you need to create an instance of the Payment object and associate it with the current sale. What class should fulfill this duty? Since in the real subject area, payment information is recorded in the registry, according to the Creator template, you can use a Register object to create an instance of the Payment object. Then an instance of the Register object will be able to send the message addPayment to the Sale object, passing as a parameter a new instance of the Payment object, as shown in Fig. 2.43.
Figure 2.43 An example interaction diagram. Low gearing
With this distribution of responsibilities, payments are made by the Register object, i.e. The Register object is partially responsible for performing the system operation makePayment.
In this particular example, this is acceptable. However, if you continue to assign to the Register class responsibilities for the implementation of new and new functions associated with other system operations, then this class will be too overloaded and will have a low degree of hooking. Suppose an application must perform fifty system operations and all of them are assigned to the Register class. If this object performs all operations, it will become excessively “bloated” and will not have the property: link. And the point is not that one task of creating an instance of a Payment object in itself reduced the degree of hooking of a Register object; it is part of the overall picture of the distribution of responsibilities.
Figure 2.44 An example interaction diagram. High gearing
Figure 2.44 presents another version of the distribution of responsibilities. Here the function of creating a payment instance is delegated to the Sale object. Due to this, a higher degree of linking of the Register object is maintained. Since this variant of the distribution of duties provides a low level of binding and a higher degree of engagement, it is more preferable. In practice, the level of engagement is not considered in isolation from other responsibilities and principles provided by the Expert and Low Coupling patterns.
When not to use a pattern
Существует несколько случаев, когда низкое зацепление оказывается оправданным. Одна из таких ситуаций возникает в том случае, когда обязанности или код группируются в одном классе или компоненте для упрощения его поддержки одним человеком. Однако в данном случае необходимо помнить о том, что такая группировка может привести и к усложнению поддержки. Например, предположим, что в приложении содержатся внедренные операторы SQL, которые в соответствии с другими шаблонами проектирования нужно распределить по десяти классам работы с базой данных. В этом случае лишь один или два эксперта в области SQL знают, как лучше всего определять и поддерживать эти операторы SQL, даже несмотря на то, что в проекте участвуют десятки программистов с опытом работы в области объектно-ориентированного программирования. Некоторые из них могут иметь достаточно высокий уровень знания объектно-ориентированных технологий. Предположим также, что эксперт в области SQL не обладает навыками программиста по созданию объектно-ориентированных программ. Архитектор программной системы может решить сгруппировать операторы SQL в одном классе RDBOperations, чтобы эксперту было легче работать с этими операторами в одном месте.
Другой пример слабого зацепления имеет отношение к распределенным серверным объектам. Поскольку быстродействие системы определяется производительностью удаленных объектов и их взаимодействием, иногда желательно создать несколько более крупных серверных объектов со слабым зацеплением, предоставляющих интерфейс многим операциям. Эта ситуация связана также с шаблоном Coarse-Grained Remote Interface (Укрупненный удаленный интерфейс), в рамках которого создаются укрупненные удаленные операции, выполняющие больше функций. Такое проектное решение объясняется повышенным влиянием удаленных вызовов на производительность сети. В качестве альтернативы вместо удаленного объекта с тремя операциями setName, setSalary и setHireDate лучше реализовать одну укрупненную удаленную операцию setDate, работающую с целым множеством данных. Это приведет к уменьшению числа удаленных вызовов и, как следствие, к повышению производительности.
Title
Don't Talk to Strangers (не разговаривай с незнакомцами). Известен, так же, под именем Law of Demeter (Закон Деметры)
Description
Паттерн этот один из самых простых, так как формализован до уровня “Делай то, не делай это”. Предназначен паттерн, как и предыдущий, для обеспечения высокого зацепления и низкой связности. Паттерн регламентирует, каким объектам, метод нашего объекта может посылать сообщения. Таковыми являются:
Все перечисленные объекты называются прямыми объектами. Все остальные – непрямые. Отсюда можно сказать, что в соответствии с паттерном Don't Talk to Strangers, метод объекта может посылать сообщения только прямым объектам и некому более. Для выполнения этого требования прямым объектам могут понадобиться новые операции, которые выступают в роли дополнительных операций, позволяющих избежать разговора с незнакомцами.
Consider an example. Предположим, что в приложении розничной торговли экземпляр класса POST, имеет атрибут, ссылающийся на объект Sale, атрибут которого, в свою очередь, ссылается на объект Payment (см. рис. 2.45).
При способе взаимодействия объектов, представленном на рис. 2.47, мы имен нарушение условий паттерна Don't Talk to Strangers. Объект POST посылает сообщение объекту Payment, хотя по условиям паттерна он не должен этого делать.
Во втором случае, условия паттерна выполняются. Но, для этого нам пришлось добавить в интерфейс объекта Sale еще один метод (paymentAmount). Такой ход называется обеспечением интерфейса (promoting the interface) и является общим решением данной проблемы.
results
Благодаря паттерну Don't Talk to Strangers нет необходимости обеспечивать видимость непрямых объектов, что в свою очередь повышает зацепление и понижает степень связности объектов.
Нарушение закона
Естественно, бывают случаи, когда условия паттерна можно (и нужно) проигнорировать. Например, при обращении объекта к объекту, организованному в соответствии с паттерном Singleton. В любом случае – Ваша задача добиться максимальной гибкости решение, а не тупо следовать рекомендациям
Рисунок 2.45. Система POST. Фрагмент диаграммы классов
Рисунок 2.46 Способов взаимодействия объектов, нарушающий закон Деметры.
Рисунок 2.47 Способов взаимодействия объектов, не нарушающий закон Деметры.
Title
Polymorphism (полиморфизм).
Task
С помощью полиморфных операций позволяет обеспечить изменяемое поведение без проверки типа. Данный паттерн является обобщением нескольких GoF-паттернов.
Decision
Условная передача управления – основной элемент любой программы. Если программа разработана с использованием условных операторов типа if-then-else, или switch-case, то при добавлении новых вариантов поведения приходится модифицировать логику условных операторов. Такой подход усложняет процесс модификации программы в соответствии с новыми вариантами поведения, поскольку изменения приходится вносить сразу в нескольких местах программного кода – там, где используются условные операторы.
Паттерн Polymorphism описывает такой способ построения системы, при котором зависящие от типа варианты поведения реализуются посредством виртуальных операций.
Example
Рассмотрим все ту же систему розничной торговли. Предположим, что оплата в этой системе может проводиться несколькими способами: наличными (CashPayment), чеком (CheckPayment) или по кредитной карте (CreditPayment). Согласно шаблону Polymorphism необходимо распределить обязанности по авторизации каждого из типа платежей. Для этого можно использовать полиморфную операцию authorize (см. рис. 2.48). Реализации каждой такой операции будут различны. Например, объект CreditPayment должен взаимодействовать со службой авторизации кредитных платежей и т.д.
Рисунок 2.48 Структура паттерна Polymorphism (пример)
results
Title
Pure Fabrication (чистая синтетика)
Task
Начну из далека. Объектно-ориентированные системы характерны тем, что программные классы часто реализуют понятия деловой среды, как например, Sale (продажа) и Employee (сотрудник). Однако, существует множество ситуаций, когда распределение обязанностей только между такими классами приводит к сильным связыванием и слабым зацеплением. Именно в таких ситуациях решением проблемы может явиться паттерн Pure Fabrication.
Decision
Присвоить группу обязанностей с высокой степенью зацепления искусственному классу, не представляющему конкретного понятия их деловой среды, т.е. синтезировать искусственную сущность для поддержки высокого зацепления, низкой связности и, как результат этого, повторного использования.
Example
Предположим, необходимо сохранять экземпляры класса Sale в базе данных. Согласно шаблону Expert эту обязанность можно присвоить самому классу Sale. Однако следует принимать во внимание следующие моменты.
Поэтому, несмотря на то, что по логике вещей класс Sale является хорошим кандидатом для выполнения обязанностей сохранения самого себя в БД, такое распределение обязанностей приводит низкой степени зацепления, высокой связности и невозможности повторного использования кода.
Естественным решением данной проблемы является создание нового класса, ответственного за сохранение объектов некоторого вида на постоянном носителе. Этот класс не выявляется из деловой среды, его там нет, он является продуктом нашего воображения и не более.
Естественно, организация хранения состояния объектов в БД – далеко не единственная задача, для решения которой может пригодиться паттерн Pure Fabrication. Многие GRASP паттерны построены на этой идее – Adapter, Visitor, Observer. Подводя итог применимости Pure Fabrication можно сказать, что с помощью этого паттерна обеспечиваются решения задач, не имеющих аналогий в деловой среде, но возникающих при программировании.
Pure Fabrication относится к абстракциям поведения (напоминаю, это вторые по полезности абстракции после абстракций сущностей).
results
Обеспечиваются паттерны Low Coupling и High Cohesion.
Проблема
Кто должен отвечать за обработку входных системных событий?
Системное событие (system event) — это событие высокого уровня, генерируемое внешним исполнителем (событие с внешним входом). Системные события связаны с системными операциями (systemoperation), т.е. операциями, выполняемыми системой в ответ на события.
Например, когда кассир в POS-системе щелкните на кнопке Оплатить, он генерирует системное событие, свидетельствующее о завершении торговой операции. Аналогично, когда пользователь текстового процессора выбирает команду Орфография, он генерирует системное событие "выполнить проверку орфографии".
Контроллер (controller) — это объект, не относящийся к интерфейсу пользователя и отвечающий за обработку системных событий. Контроллер определяет методы для выполнения системных операций.
Decision
Делегирование обязанностей по обработке системных сообщений классу, удовлетворяющему одному из следующих условий.
Следствие. Заметим, что в этот перечень не включаются классы, реализующие окно, аплет, приложение, вид и документ. Такие классы не выполняют задачи, связанные с системными событиями. Они обычно получают сообщения и делегируют их контроллерам.
Benefits
Улучшение условий для повторного использования компонентов. Применение этого шаблона обеспечивает обработку процессов предметной области на уровне реализации объектов, а не на уровне интерфейса. Обязанности контроллера могут быть технически реализованы в объектах интерфейса, однако в этом случае программный код и логические решения, относящиеся к процессам предметной области, будут жестко связаны с элементами интерфейса, например с окнами. При этом снижается эффективность повторного использования компонентов в других приложениях, поскольку процессы предметной области ограничены рамками интерфейса (например, связаны с оконным объектом), что может оказаться неприемлемым в других прило жениях. Делегирование выполнения системных операций специальному контроллеру облегчает повторное использование логики обработки подобных процессов в последующих приложениях.
Контроль состояния прецедента. Иногда необходимо удостовериться, что системные операции выполняются в некоторой определенной последовательности. Например, необходимо гарантировать, чтобы операция makePayment выполнялась только после операции EndSale, для чего необходимо накапливать информацию о последовательности событий. Для этой цели удобно использовать контроллер, особенно контроллер прецедента.
Раздутый контроллер
Плохо спроектированный класс контроллера имеет низкую степень зацепления: он выполняет слишком много обязанностей и является несфокусированным. Такой контроллер называется раздутым (bloated controller). Признаки раздутого контроллера таковы.
В системе имеется единственный класс контроллера, получающий все системные сообщения, которых поступает слишком много. Такая ситуация зачастую возникает при использовании внешнего контроллера.
Контроллер сам выполняет все задачи, не делегируя обязанности другим классам. Обычно это приводит к нарушению основных принципов шаблонов Information Expert и High Cohesion.
Контроллер имеет много атрибутов и содержит значительный объем информации о системе или предметной области, которую необходимо распределить между другими объектами, либо дублирует информацию, хранящуюся в других объектах.
Часть 1 2.4 Patterns of behavior
Часть 2 2.4.9 High Cohesion Pattern - 2.4 Patterns of behavior
Comments
To leave a comment
Object oriented programming
Terms: Object oriented programming