Когда не следует применять шаблон.



Зачастую создание экземпляра — это достаточно сложная операция, выполняемая при реализации некоторого условия на основе каких-либо внешних свойств. В этом случае предпочтительнее использовать шаблон Factory (Фабрика) и делегировать обязанность создания экземпляров вспомогательному классу.

Преимущества

§ Поддерживается шаблон Low Coupling, способствующий снижению затрат на сопровождение и обеспечивающий возможность повторного использования созданных компонентов в дальнейшем.

§ Применение шаблона Creator не повышает степени связанности, поскольку созданный класс, как правило, оказывается видимым для класса-создателя посредством имеющихся ассоциаций.


GRASP: принцип Pure Fabrication.

Проблема. Какой класс должен обеспечить реализацию шаблонов High Cohesion и Low Coupling или других принципов проектирования, если шаблон Information Expert (например) не обеспечивает подходящего решения?

Объектно-ориентированные системы отличаются тем, что программные классы реализуют понятия предметной области, как, например, классы Sale и Customer. Однако существует множество ситуаций, когда распределение обязанностей только между такими классами приводит к проблемам с зацеплением и связыванием, т. е. с невозможностью повторного использования кода.

Решение. Присвоить группу обязанностей с высокой степенью зацепления искусственному классу, не представляющему конкретного понятия из предметной области, т. е. синтезировать искусственную сущности для поддержки высокого зацепления, слабого связывания и повторного использования. Такой класс является продуктом нашего воображения и представляет собой синтетику (fabrication). В идеале, присвоенные этому классу обязанности поддерживают высокую степень зацепления и низкое связывание, так что структура этого синтетического класса является очень прозрачной или чистой (pure). Отсюда и название: Pure Fabrication («чистая синтетика»).

Пример. Предположим, необходимо сохранять экземпляры класса Sale в реляционной базе данных. Согласно шаблону Information Expert, эту обязанность можно присвоить самому классу Sale. Однако следует принять во внимание следующие моменты:

§ данная задача требует достаточно большого числа специализированных операций, связанных со взаимодействием с базой данных и никак не связанных с понятием самой продажи. Поэтому класс Sale получает низкую степень зацепления;

§ класс Sale должен быть связан с интерфейсом реляционной базы данных (таким как JDBC для технологии Java). Поэтому возрастает степень связывания, причем даже не с другим объектом предметной области, а с интерфейсом базы данных;

§ хранение объектов в реляционной базе данных — это достаточно общая задача, решение которой необходимо для многих классов. Возлагая эту обязанность на класс Sale, разработчик не обеспечивает возможности повторного использования этих операций и вынужден дублировать их в других классах.

Поэтому, несмотря на то, что класс Sale является хорошим кандидатом для выполнения обязанности самосохранения в базе данных, согласно шаблону Information Expert, такое распределение обязанностей приводит к низкой степени зацепления, сильному связыванию и невозможности повторного использования кода. Естественным решением данной проблемы является создание нового класса, ответственного за сохранение объектов некоторого вида на постоянном носителе, например в реляционной БД. Его можно назвать PersistentStorage (Постоянное хранилище). Этот класс является продуктом нашего воображения, что полностью соответствует шаблону Pure Fabrication.

Обратите внимание на имя класса PersistentStorage, оно вполне понятно,

хотя объект с аналогичным названием отсутствует в модели предметной области. PersistentStorage — это не понятие из предметной области, а нечто, синтезированное для удобства разработчика программы.

Этот чисто синтетический объект решает следующие задачи.

§ класс Sale сохраняет высокую степень зацепления и слабое связывание;

§ класс PersistentStorage также обладает этими свойствами, выполняя единственную задачу: сохранение объектов на постоянном носителе;

§ класс PersistentStorage является достаточно общим и допускает повторное использование.

Этот пример — типичная ситуация для создания «чисто синтетического» класса. Он позволяет избежать проблем с зацеплением и связыванием и обеспечивает новые возможности для повторного использования.

Обратите внимание, что, подобно остальным, шаблонам GRASP, в данном шаблоне основное внимание уделяется распределению обязанностей. В нашем примере обязанности передаются от класса Sale (выбранного согласно шаблону Expert) новому «чисто синтетическому» классу.

Обсуждение. Проектируемые объекты делятся на две следующие группы:

1) создаваемые на основе декомпозиции представления;

2) создаваемые на основе декомпозиции поведения.

Например, программный класс Sale был создан на основе декомпозиции представления, поскольку он представляет понятие предметной области (или связан с ним). Декомпозиция представления — это типичная стратегия объектного проектирования, позволяющая сократить разрыв между реальными объектами и их программным представлением. Однако иногда возникает потребность распределить обязанности на основе однотипного поведения или реализации некоторого алгоритма, не привязываясь к понятиям реального мира.

Хорошим примером объекта-алгоритма является генератор оглавления TableOfContentsGenerator. Это вспомогательный класс, не имеющий аналога в словаре терминов из предметной области книг или документов. Он предназначен для удобства разработчиков, поскольку в нем сосредоточены методы, реализующие некоторое однотипное поведение. То есть этот класс создан на основе декомпозиции поведения.

Вспомогательный класс не обязательно должен быть «чисто синтетическим». Это название служит скорее целям обучения, поскольку отражает общую идею распределения обязанностей между программными классами: некоторые классы представляют понятия предметной области, а

другие создаются просто для удобства разработчиков. Эти вспомогательные классы зачастую объединяются в группы на основе общности поведения и соответствуют принципу декомпозиции поведения, а не представления. Другими словами, согласно шаблону Pure Fabrication, классы проектируются на основе общей функциональности и представляют собой поведенческие или функционально-ориентированные объекты.

Многие существующие шаблоны объектно-ориентированного проектирования являются примерами использования шаблона Pure Fabrication. К ним можно отнести шаблоны Adapter, Strategy, Command и т.д.

Назначение:

· При использовании шаблона Pure Fabrication реализуется шаблон High Cohesion, поскольку обязанности передаются отдельному классу, сконцентрированному на решении специфического набора взаимосвязанных задач.

· Повышается потенциал повторного использования, поскольку чисто синтетические классы можно применять в других приложениях.

Когда не следует применять шаблон. Новички в области объектно-ориентированного проектирования, имеющие опыт разработки программ в рамках структурного или функционального подхода, зачастую «злоупотребляют» использованием шаблона Pure Fabrication. В их трактовке функции просто превращаются в объекты.

Нет ничего предосудительного в создании функционально-ориентированных или алгоритмически-ориентированных объектов. Однако необходимо соблюдать пропорции между количеством таких объектов и объектов, созданных на основе декомпозиции представления, согласно шаблону Information Expert. Класс Sale тоже имеет право на существование и должен выполнять свои обязанности. Созданные на основе шаблона Information Expert объекты обладают информацией, необходимой для выполнения своих обязанностей и соответствуют принципу слабого связывания объектов. При «злоупотреблении» применением шаблона Pure Fabrication нарушаются требования к слабому связыванию объектов. Типичным симптомом такой ситуации является необходимость передачи данных одного объекта другим объектам для выполнения действий над ними.

 


GRASP: принцип Indirection.

Проблема. Как распределить обязанности, чтобы обеспечить отсутствие прямого связывания? Как снизить уровень связывания объектов, согласно шаблону Low Coupling, и сохранить высокий потенциал повторного использования?

Решение. Присвоить обязанности промежуточному объекту для обеспечения связи между другими компонентами или службами, которые не связаны между собой напрямую.

При таком подходе связи перенаправляются к другим компонентами или службами.

Примеры

Класс Modem. Рассмотрим службу авторизации кредитной карты — класс CreditAuthorizationService. Допустим, что реализации этого класса необходимо использовать модем.

Самым простым решением было бы использовать низкоуровневые вызовы API модема в методах класса CreditAuthorizationService. Но при этом разрабатываемый класс достаточно сильно привязывается к API модема, что значительно снижает возможности по его повторному использованию и модификации.

Лучшим решением является добавление посредника — класса Modem, который изолирует класса CreditAuthorizationService от API модема (рис. 9).

 

 

Рис. 9. Использование класса Modem для изоляции службы авторизации кредитных карт от низкоуровневого API модема

Класс PersistentStorage. В примере, приведенном при рассмотрении шаблона Pure Fabrication, класс Sale отделяется от служб взаимодействия с реляционной базой данных посредством введения класса PersistentStorage. Этот же пример соответствует реализации шаблона Indirection. Класс PersistentStorage выступает в роли промежуточного звена между классом Sale и БД.

Назначение. «Большинство проблем, связанных с компьютерными науками, можно решить с помощью нового уровня перенаправления (Дэвид Виллер)» — это старая истина, применимая и к объектно-ориентированному проектированию.

Точно также, как многие шаблоны проектирования являются частным случаем шаблона Pure Fabrication, существует множество специализированных вариантов шаблона Indirection. Примерами таких шаблонов являются Adapter, Facade и Observer. Кроме того, многие вариации

шаблона Pure Fabrication зачастую базируются на основном принципе перенаправления связи по шаблону Indirection. Целью такого перенаправления обычно является слабое связывание, обеспечиваемое за счет отделения друг от друга различных компонентов или служб.

Замечание. Существует также и высказывание: «Большинство проблем, связанных с производительностью, можно решить, удалив новый уровень перенаправления».

Преимущество: слабое связывание между компонентами.

 


58.GRASP: принцип Polymorphism.

Проблема. Как обрабатывать альтернативные варианты поведения на основе типа?

Условная передача управления — это основная отличительная особенность любой программы. Если программа разработана с использованием условных операторов типа if-then-else (если-то-иначе) или операторов условного перехода по ключу, то при добавлении новых вариантов поведения приходится модифицировать логику условных операторов. Такой подход затрудняет процесс модификации программ в соответствии с новыми вариантами поведения, поскольку изменения приходится вносить сразу в нескольких местах программного кода — там, где используются условные операторы.

Решение. Если поведение объектов одного типа (класса) может изменяться, обязанности распределяются для различных вариантов поведения с использованием полиморфных операций для этого класса (а не с использованием проверки типа или условной логики).

Пример. POS-система NextGen должна поддерживать работу различных внешних систем вычисления налоговых платежей (в том числе Tax-Master и Good-As-Gold TaxPro) и интеграцию с другими внешними системами. Каждая система вычисления налоговых платежей имеет свой интерфейс и обладает собственным поведением (хотя и аналогичным поведению других систем). Один продукт может поддерживать протокол TCP, другой — интерфейс SOAP, а третий — интерфейс Java RMI.

 

 

Рис. 10. Использование полиморфизма при адаптации к различным внешним системам вычисления налоговых платежей

Какие объекты должны отвечать за обработку различных внешних интерфейсов систем вычисления налоговых платежей?

Поскольку поведение службы адаптации внешней системы вычисления налоговых платежей зависит от типа используемой программы вычисления, согласно шаблону Polymorphism, необходимо распределить обязанности по адаптации к различным типам этих программ. Для этого можно использовать полиморфную операцию getTaxes (рис. 10).

Каждому методу getTaxes в качестве параметра передается объект Sale, чтобы система вычисления налоговых платежей могла проанализировать продажу. Реализации каждого такого метода отличаются. Например, объект TaxMasterAdapter может адаптировать запросы к системе Tax-Master и т.п.

Назначение

· С помощью шаблона впоследствии можно легко расширять систему, добавляя в нее новые вариации.

· Новые реализации можно вводить без модификации клиентской части приложения.

Обсуждение. Полиморфизм — это основной принцип проектирования поведения системы в рамках обработки аналогичных ситуаций. Если обязанности в системе распределены на основе шаблона Polymorphism, то такую систему можно легко модифицировать, добавляя в нее новые

вариации.

Полиморфизм предполагает реализацию с использованием абстрактных классов или интерфейсов. Когда следует применять интерфейсы? Общая рекомендация состоит в том, что интерфейсы добавляются для поддержки полиморфизма при неизвестной заранее иерархии классов. Более того, интерфейсы обеспечивают «гибкую точку» вариаций для неизвестных ситуаций.

Если же используется абстрактный суперкласс, и поведение по умолчанию в нем не определяется, то полиморфную операцию в нем следует объявить абстрактной.

Когда не следует применять шаблон. Иногда разработчики систем злоупотребляют добавлением интерфейсов и применением принципа полиморфизма с целью обеспечения дееспособности системы в неизвестных заранее новых ситуациях. Если точка вариаций известна и обоснована, если существует высокая вероятность вариантного поведения, то такие усилия по обеспечению гибкости системы и применению принципа полиморфизма вполне оправданы. Однако к применению этого принципа нужно подходить критически, поскольку зачастую усилия по обеспечению вариантов поведения «на все случаи жизни» затрачиваются впустую.

 


Дата добавления: 2018-05-13; просмотров: 597; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!