Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

2.4.7 Паттерн Chain Of Responsibility - 2.4 Паттерны поведения

Лекция



Это продолжение увлекательной статьи про паттерны поведения.

...

операции);

  • фабричные методы (см. паттерн фабричный метод);
  • операции-зацепки (hook operations), реализующие поведение по умолчанию, которое может быть расширено в подклассах. Часто такая операция по умолчанию не делает ничего.
  • Важно, чтобы в шаблонном методе четко различались операции-зацепки (которые можно замещать) и абстрактные операции (которые нужно замещать). Чтобы повторно использовать абстрактный класс с максимальной эффективностью, авторы подклассов должны понимать, какие операции предназначены для замещения.

    Подкласс может расширить поведение некоторой операции, заместив ее и явно вызвав эту операцию из родительского класса:

    void DerivedClass::0peration ()

    {

    ParentClass::Operation));

    // Расширенное поведение класса DerivedClass

    }

    К сожалению, очень легко забыть о необходимости вызывать унаследованную операцию. У нас есть возможность трансформировать такую операцию в шаблонный метод с целью предоставить родителю контроль над тем, как подклассы расширяют его. Идея в том, чтобы вызывать операцию-зацепку из шаблонного метода в родительском классе. Тогда подклассы смогут переопределить именно эту операцию:

    void ParentClass::Operation ()

    {

    // Поведение родительского класса ParentClass

    HookOperation();

    }

    В родительском классе ParentClass операция Hook0peration не делает ничего:

    void ParentClass::HookOperation ()

    {

    }

    Но она замещена в подклассах, которые расширяют поведение:

    void DerivedClass::HookOperation ()

    {

    // расширение в производном классе

    }

    2.4.7 Паттерн Chain Of Responsibility

    Название

    Chain Of Responsibility (цепочка обязанностей)

    Назначение

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

    Мотивация

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

    Поэтому естественно было бы организовать справочную информацию от более конкретных разделов к более общим. Кроме того, ясно, что запрос на получение справки обрабатывается одним из нескольких объектов пользовательского интерфейса, каким именно - зависит от контекста и имеющейся в наличии информации. Проблема в том, что объект, инициирующий запрос (например, кнопка), не располагает информацией о том, какой объект в конечном итоге предоставит справку. Нам необходим какой-то способ отделить кнопку-инициатор запроса от объектов, владеющих справочной информацией. Как этого добиться, показывает паттерн Цепочка обязанностей. Идея заключается в том, чтобы разорвать связь между отправителями и получателями, дав возможность обработать запрос нескольким объектам. Запрос перемещается по цепочке объектов, пока один из них не обработает его. Первый объект в цепочке получает запрос и либо обрабатывает его сам, либо направляет следующему кандидату в цепочке, который ведет себя точно так же. у объекта, отправившего запрос, отсутствует информация об обработчике. Мы говорим, что у запроса есть анонимный получатель (implicit receiver).

    Предположим, что пользователь запрашивает справку по кнопке Print (печать). Она находится в диалоговом окне PrintDialog, содержащем информацию об объекте приложения, которому принадлежит (см. предыдущую диаграмму объектов). На представленной на рис. 2.34 диаграмме взаимодействий показано, как запрос на получение справки перемещается по цепочке.

    2.4      Паттерны поведения

    Рисунок 2.35 Паттерн Chain of Responsibility. Отношения между объектами

    2.4      Паттерны поведения

    Рисунок 2.36 Паттерн Chain of Responsibility. Обработка сообщения

    В данном случае ни кнопка aPrintButton, ни окно aPrintDialog не обрабатывают запрос, он достигает объекта anApplication, который может его обработать или игнорировать. У клиента, инициировавшего запрос, нет прямой ссылки на объект, который его в конце концов выполнит

    Чтобы отравить запрос по цепочке и гарантировать анонимность получателя, все объекты в цепочке имеют единый интерфейс для обработки запросов и для доступа к своему преемнику (следующему объекту в цепочке). Например, в системе оперативной справки можно было бы определить класс HelpHandler (предок классов всех объектов-кандидатов или подмешиваемый класс (mixin class)) с операцией HandleHelp. Тогда классы, которые будут обрабатывать запрос, смогут его передать своему родителю.

    Для обработки запросов на получение справки классы Button, PrintDialog и Application пользуются операциями HelpHandler. По умолчанию HandleHelp просто перенаправляет запрос своему преемнику. В подклассах эта операция замещается, так что при благоприятных обстоятельствах может выдаваться справочная информация. В противном случае запрос отправляется дальше посредством реализации по умолчанию.

    2.4      Паттерны поведения

    Рисунок 2.37 Структура паттерна Chain of Responsibility (пример)

    Применимость

    • Есть более одного объекта, способного обработать запрос, причем настоящий обработчик, заранее неизвестен и должен быть найден автоматически.
    • Вы хотите отправить запрос одному из нескольких объектов, не указывая явно, какому именно;
      набор объектов, способных обработать запрос, должен задаваться динамически.

    Структура

    2.4      Паттерны поведения

    Рисунок 2.38 Структура паттерна Chain of Responsibility

    Результаты

    • Ослабление связанности. Этот паттерн освобождает объект от необходимости «знать», кто конкретно обработает его запрос. Отправителю и получателю ничего неизвестно друг о друге, а включенному в цепочку объекту о структуре цепочки. Таким образом, цепочка обязанностей помогает упростить взаимосвязи между объектами. Вместо того чтобы хранить ссылки на все объекты, которые могут стать получателями запроса, объект должен располагать информацией лишь о своем ближайшем преемнике;
    • Дополнительная гибкость при распределении обязанностей между объектами. Цепочка обязанностей позволяет повысить гибкость распределения обязанностей между объектами. Добавить или изменить обязанности по обработке запроса можно, включив в цепочку новых участников или изменив ее каким-то другим образом. Этот подход можно сочетать со статическим порождением подклассов для создания специализированных обработчиков;
    • Получение не гарантировано. Поскольку у запроса нет явного получателя, то нет и гарантий, что он вообще будет обработан: он может достичь конца цепочки и пропасть. Необработанным запрос может оказаться и в случае неправильной конфигурации цепочки.

    2.4.8 Паттерн Command

    Название

    Command (команда), Action (действие), Transaction (транзакция)

    Назначение

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

    Мотивация

    Иногда необходимо посылать объектам запросы, ничего не зная о том, выполнение какой операции запрошено и кто является получателем. Например, в библиотеках для построения пользовательских интерфейсов встречаются такие объекты, как кнопки и меню, которые посылают запрос в ответ на действие пользователя. Но и саму библиотеку не заложена возможность обрабатывать этот запрос, так как только приложение, использующее ее, располагает информацией о том, что следует сделать. Проектировщик библиотеки не владеет никакой информацией о получателе запроса и о том, какие операции тот должен выполнить. Паттерн команда позволяет библиотечным объектам отправлять запросы неизвестным объектам приложения, преобразовав сам запрос в объект. Этот объект можно хранить и передавать, как и любой другой. В основе списываемого паттерна лежит абстрактный класс Command, в котором объявлен интерфейс для выполнения операций. В простейшей своей форме этот интерфейс состоит из одной абстрактной операции Execute. Конкретные подклассы Command определяют пару “получатель-действие”, сохраняя получателя в переменной экземпляра, и реализуют операцию Execute, так чтобы она посылала запрос. У получателя есть информация, необходимая для выполнения запроса.

    2.4      Паттерны поведения

    Рисунок 2.39 Структура паттерна Command (пример)

    С помощью объектов Command легко реализуются меню. Каждый пункт меню -это экземпляр класса Menultem. Сами меню и все их пункты создает класс Application наряду со всеми остальными элементами пользовательского интерфейса. Класс Application отслеживает также открытые пользователем документы.

    Приложение конфигурирует каждый объект Menultem экземпляром конкретного подкласса Command. Когда пользователь выбирает некоторый пункт меню, ассоциированный с ним объект Menultem вызывает Execute для своего объекта-команды, a Execute выполняет операцию. Объекты Menultem не имеют информации, какой подкласс класса Command они используют. Подклассы Command хранят информацию о получателе запроса и вызывают одну или несколько операций этого получателя.

    Например, подкласс PasteCommand поддерживает вставку текста из буфера обмена в документ. Получателем для PasCeCommand является Document, который был передан при создании объекта. Операция Execute вызывает операцию Paste документа-получателя.

    Для подкласса OpenCommand операция Execute ведет себя по-другому: она запрашивает у пользователя имя документа, создает соответствующий объект Document, извещает о новом документе приложение-получатель и открывает этот документ.

    Иногда объект Menultem должен выполнить последовательность команд-Например, пункт меню для центрирования страницы стандартного размера можно было бы сконструировать сразу из двух объектов: CenterDocumentCommand и NormalsizeCommand. Поскольку такое комбинирование команд - явление обычное, то мы можем определить класс MacroCommand, позволяющий объекту Menultem выполнять произвольное число команд. MacroCommand - это конкретный подкласс класса Command, который просто выполняет последовательность команд. У него нет явного получателя, поскольку для каждой команды определен свой собственный.

    Обратите внимание, что в каждом из приведенных примеров паттерн команда отделяет объект, инициирующий операцию, от объекта, который «знает», как ее выполнить. Это позволяет добиться высокой гибкости при проектировании пользовательского интерфейса. Пункт меню и кнопка одновременно могут быть ассоциированы в приложении с некоторой функцией, для этого достаточно приписать обоим элементам один и тот же экземпляр конкретного подкласса класса Command. Мы можем динамически подменять команды, что очень полезно для реализации контекстно-зависимых меню. Можно также поддержать сценарии, если компоновать простые команды в более сложные. Все это выполнимо потому, что объект, инициирующий запрос, должен располагать информацией лишь о том. как его отправить, а не о том, как его выполнить.

    2.4      Паттерны поведения

    Рисунок 2.40. Паттерн Command. Макрокоманда.

    Применимость

    • хотите параметризовать объекты выполняемым действием, как в случае с пунктами меню Menultem. В процедурном языке такую параметризацию можно выразить с помощью функции обратного вызова, то есть такой функции, которая регистрируется, чтобы быть вызванной позднее. Команды представляют собой объектно-ориентированную альтернативу функциям обратного вызова;
    • нужно определять, ставить в очередь и выполнять запросы в разное время. Время жизни объекта Command необязательно должно зависеть от времени жизни исходного запроса. Если получателя запроса удается реализовать так, чтобы он не зависел от адресного пространства, то объект-команду можно передать другому процессу, который займется его выполнением;
    • хотите поддержать отмену операций. Операция Execute объекта Command может сохранить состояние, необходимое для отката действий, выполненных командой. В этом случае в интерфейсе класса Command должна быть дополнительная операция Unexecute, которая отменяет действия, выполненные предшествующим обращением к Execute. Выполненные команды хранятся в списке истории. Для реализации произвольного числа уровней отмены и повтора команд нужно обходить этот список соответственно в обратном и прямом направлениях, вызывая при посещении каждого элемента команду Unexecute или Execute;
    • хотите поддержать протоколирование изменений, чтобы их можно было выполнить повторно после аварийной остановки системы. Дополнив интерфейс класса Command операциями сохранения и загрузки, вы сможете вести протокол изменений во внешней памяти. Для восстановления после сбоя нужно будет загрузить сохраненные команды с диска и повторно выполнить их с помощью операции Execute;
    • необходимо структурировать систему на основе высокоуровневых операций, построенных из примитивных. Такая структура типична для информационных систем, поддерживающих транзакции. Транзакция инкапсулирует набор изменений данных. Паттерн команда позволяет моделировать транзакции. У всех команд есть общий интерфейс, что дает возможность работать одинаково с любыми транзакциями. С помощью этого паттерна можно легко добавлять в систему новые виды транзакций.

    Результаты

    • команда разрывает связь между объектом, инициирующим операцию, и объектом, имеющим информацию о том, как ее выполнить;
    • команды - это самые настоящие объекты. Допускается манипулировать ими и расширять их точно так же, как в случае с любыми другими объектами;
    • из простых команд можно собирать составные, например класс MacroCommand, рассмотренный выше. В общем случае составные команды описываются паттерном компоновщик;
    • добавлять новые команды легко, поскольку никакие существующие классы изменять не нужно.

    Структура

    2.4      Паттерны поведения

    Рисунок 2.41 Структура паттерна Command

    На следующей диаграмме (рис. 2.42) видно, как Command разрывает связь между инициатором и получателем (а также запросом, который должен выполнить последний).

    2.4.9 Паттерн High Cohesion

    Название

    High Cohesion (слабое зацепление)

    Проблема

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

    2.4      Паттерны поведения

    Рисунок 2.42 Паттерн Command. Взаимодействие объектов

    В роли таких элементов могут выступать классы, подсистемы и т.д. Класс с низкой степенью зацепления выполняет много разнородных функций или несвязанных между собой обязанностей. Такие классы создавать нежелательно, поскольку они приводят к возникновению следующих проблем.

    • Трудность понимания.
    • Сложности при повторном использовании.
    • Сложности поддержки.
    • Ненадежность, постоянная подверженность изменениям.

    Классы со слабым зацеплением, как правило, являются слишком "абстрактными" или выполняют обязанности, которые можно легко распределить между другими объектами.

    Решение

    Распределение обязанностей, поддерживающее высокую степень зацепления.

    Результаты

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

    Пример

    Для анализа шаблона High Cohesion можно использовать тот же пример, что и для Low Coupling. Предположим, необходимо создать экземпляр объекта Payment и связать его с текущей продажей. Какой класс должен выполнять эту обязанность? Поскольку в реальной предметной области сведения о платежах записываются в реестре, согласно шаблону Creator, для создания экземпляра объекта Payment можно использовать объект Register. Тогда экземпляр объекта Register сможет отправить сообщение addPayment объекту Sale, передавая в качестве параметра новый экземпляр объекта Payment, как показано на рис. 2.43.

    2.4      Паттерны поведения

    Рисунок 2.43 Пример диаграммы взаимодействия. Низкое зацепление

    При таком распределении обязанностей платежи выполняет объект Register, т.е. объект Register частично несет ответственность за выполнение системной операции makePayment.
    В данном обособленном примере это приемлемо. Однако если и далее возлагать на класс Register обязанности по выполнению все новых и новых функций, связанных с другими системными операциями, то этот класс будет слишком перегружен и будет обладать низкой степенью зацепления. Предположим, приложение должно выполнять пятьдесят системных операций и все они возложены на класс Register. Если этот объект будет выполнять все операции, то он станет чрезмерно "раздутым" и не будет обладать свойством: зацепления. И дело не в том, что одна задача создания экземпляра объекта Payment сама по себе снизила степень зацепления объекта Register; она является частью общей картины распределения обязанностей.

    2.4      Паттерны поведения

    Рисунок 2.44 Пример диаграммы взаимодействия. Высокое зацепление

    На рис 2.44 представлен другой вариант распределения обязанностей. Здесь функция создания экземпляра платежа делегирована объекту Sale. Благодаря этому поддерживается более высокая степень зацепления объекта Register. Поскольку такой вариант распределения обязанностей обеспечивает низкий уровень связывания и более высокую степень зацепления, он является более предпочтительным. На практике уровень зацепления не рассматривают изолированно от других обязанностей и принципов, обеспечиваемых шаблонами Expert и Low Coupling.

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

    Существует несколько случаев, когда низкое зацепление оказывается оправданным. Одна из таких ситуаций возникает в том случае, когда обязанности или код группируются в одном классе или компоненте для упрощения его поддержки одним человеком. Однако в данном случае необходимо помнить о том, что такая группировка может привести и к усложнению поддержки. Например, предположим, что в приложении содержатся внедренные операторы SQL, которые в соответствии с другими шаблонами проектирования нужно распределить по десяти классам работы с базой данных. В этом случае лишь один или два эксперта в области SQL знают, как лучше всего определять и поддерживать эти операторы SQL, даже несмотря на то, что в проекте участвуют десятки программистов с опытом работы в области объектно-ориентированного программирования. Некоторые из них могут иметь достаточно высокий уровень знания объектно-ориентированных технологий. Предположим также, что эксперт в области SQL не обладает навыками программиста по созданию объектно-ориентированных программ. Архитектор программной системы может решить сгруппировать операторы SQL в одном классе RDBOperations, чтобы эксперту было легче работать с этими операторами в одном месте.

    Другой пример слабого зацепления имеет отношение к распределенным серверным объектам. Поскольку быстродействие системы определяется производительностью удаленных объектов и их взаимодействием, иногда желательно создать несколько более крупных серверных объектов со слабым зацеплением, предоставляющих интерфейс многим операциям. Эта ситуация связана также с шаблоном Coarse-Grained Remote Interface (Укрупненный удаленный интерфейс), в рамках которого создаются укрупненные удаленные операции, выполняющие больше функций. Такое проектное решение объясняется повышенным влиянием удаленных вызовов на производительность сети. В качестве альтернативы вместо удаленного объекта с тремя операциями setName, setSalary и setHireDate лучше реализовать одну укрупненную удаленную операцию setDate, работающую с целым множеством данных. Это приведет к уменьшению числа удаленных вызовов и, как следствие, к повышению производительности.

    2.4.10 Паттерн Don’t Talk To Strangers

    Название

    Don’t Talk to Strangers (не разговаривай с незнакомцами). Известен, так же, под именем Law of Demeter (Закон Деметры)

    Описание

    Паттерн этот один из самых простых, так как формализован до уровня “Делай то, не делай это”. Предназначен паттерн, как и предыдущий, для обеспечения высокого зацепления и низкой связности. Паттерн регламентирует, каким объектам, метод нашего объекта может посылать сообщения. Таковыми являются:

    • Объекту this (self).
    • Параметрам метода.
    • Атрибуту объекта this (self).
    • Элементу контейнера, являющемуся атрибутом this (self).
    • Объекту, созданному внутри метода.

    Все перечисленные объекты называются прямыми объектами. Все остальные – непрямые. Отсюда можно сказать, что в соответствии с паттерном Don’t Talk to Strangers, метод объекта может посылать сообщения только прямым объектам и некому более. Для выполнения этого требования прямым объектам могут понадобиться новые операции, которые выступают в роли дополнительных операций, позволяющих избежать разговора с незнакомцами.

    Рассмотрим пример. Предположим, что в приложении розничной торговли экземпляр класса POST, имеет атрибут, ссылающийся на объект Sale, атрибут которого, в свою очередь, ссылается на объект Payment (см. рис. 2.45).

    При способе взаимодействия объектов, представленном на рис. 2.47, мы имен нарушение условий паттерна Don’t Talk to Strangers. Объект POST посылает сообщение объекту Payment, хотя по условиям паттерна он не должен этого делать.

    Во втором случае, условия паттерна выполняются. Но, для этого нам пришлось добавить в интерфейс объекта Sale еще один метод (paymentAmount). Такой ход называется обеспечением интерфейса (promoting the interface) и является общим решением данной проблемы.

    Результаты

    Благодаря паттерну Don’t Talk to Strangers нет необходимости обеспечивать видимость непрямых объектов, что в свою очередь повышает зацепление и понижает степень связности объектов.

    Нарушение закона

    Естественно, бывают случаи, когда условия паттерна можно (и нужно) проигнорировать. Например, при обращении объекта к объекту, организованному в соответствии с паттерном Singleton. В любом случае – Ваша задача добиться максимальной гибкости решение, а не тупо следовать рекомендациям

    2.4      Паттерны поведения

    Рисунок 2.45. Система POST. Фрагмент диаграммы классов

    2.4      Паттерны поведения

    Рисунок 2.46 Способов взаимодействия объектов, нарушающий закон Деметры.

    2.4      Паттерны поведения

    Рисунок 2.47 Способов взаимодействия объектов, не нарушающий закон Деметры.

    2.4.11 Паттерн Polymorphism

    Название

    Polymorphism (полиморфизм).

    Задача

    С помощью полиморфных операций позволяет обеспечить изменяемое поведение без проверки типа. Данный паттерн является обобщением нескольких GoF-паттернов.

    Решение

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

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

    Пример

    Рассмотрим все ту же систему розничной торговли. Предположим, что оплата в этой системе может проводиться несколькими способами: наличными (CashPayment), чеком (CheckPayment) или по кредитной карте (CreditPayment). Согласно шаблону Polymorphism необходимо распределить обязанности по авторизации каждого из типа платежей. Для этого можно использовать полиморфную операцию authorize (см. рис. 2.48). Реализации каждой такой операции будут различны. Например, объект CreditPayment должен взаимодействовать со службой авторизации кредитных платежей и т.д.

    2.4      Паттерны поведения

    Рисунок 2.48 Структура паттерна Polymorphism (пример)

    Результаты

    • Паттерн позволяет легко расширять систему, добавляя в нее новое поведение и не изменяя при этом клиентов, относительно этого поведения.

    2.4.12 Паттерн Pure Fabrication

    Название

    Pure Fabrication (чистая синтетика)

    Задача

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

    Решение

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

    Пример

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

    • Данная задача требует выполнения достаточно большого количества специализированных операций, связанных со взаимодействием с базой данных и не как не связанных с понятием самой продажи. Поэтому класс Sale получает низкую степень зацепления.
    • Класс Sale, при условии, что он сам сохраняет себя в БД, должен быть связан с интерфейсом БД. Поэтому возрастает степень связности, причем даже не с другим объектом деловой среды, а с интерфейсом БД.
    • Хранение объектов в БД – это достаточно общая задача, решение которой необходимо для многих классов. Возлагая эту обязанность на класс Sale, разработчик не обеспечивает возможности повторного использования данный операций и вынужден дублировать их во многих классах.

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

    Естественным решением данной проблемы является создание нового класса, ответственного за сохранение объектов некоторого вида на постоянном носителе. Этот класс не выявляется из деловой среды, его там нет, он является продуктом нашего воображения и не более.

    Естественно, организация хранения состояния объектов в БД – далеко не единственная задача, для решения которой может пригодиться паттерн Pure Fabrication. Многие GRASP паттерны построены на этой идее – Adapter, Visitor, Observer. Подводя итог применимости Pure Fabrication можно сказать, что с помощью этого паттерна обеспечиваются решения задач, не имеющих аналогий в деловой среде, но возникающих при программировании.

    Pure Fabrication относится к абстракциям поведения (напоминаю, это вторые по полезности абстракции после абстракций сущностей).

    Результаты

    Обеспечиваются паттерны Low Coupling и High Cohesion.

    2.4.13 Паттерн Controller

    Проблема

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

    Системное событие (system event) — это событие высокого уровня, генерируемое внешним исполнителем (событие с внешним входом). Системные события связаны с системными операциями (systemoperation), т.е. операциями, выполняемыми системой в ответ на события.

    Например, когда кассир в POS-системе щелкните на кнопке Оплатить, он генерирует системное событие, свидетельствующее о завершении торговой операции. Аналогично, когда пользователь текстового процессора выбирает команду Орфография, он генерирует системное событие "выполнить проверку орфографии".

    Контроллер (controller) — это объект, не относящийся к интерфейсу пользователя и отвечающий за обработку системных событий. Контроллер определяет методы для выполнения системных операций.

    Решение

    Делегирование обязанностей по обработке системных сообщений классу, удовлетворяющему одному из следующих условий.

    • Класс представляет всю систему в целом, устройство или подсистему (внешний контроллер).
    • Класс представляет сценарий некоторого прецедента, в рамках которого выполняется обработка всех системных событий, и обычно называется <Прецедент>Наndlег,<Прецедент>Coordinator или <Прецедент> Session (контроллер прецедента или контроллер сеанса).
    • Для всех системных событий в рамках одного сценария прецедента используется один и тот же класс-контроллер.
    • Неформально, сеанс — это экземпляр взаимодействия с исполнителем. Сеансы могут иметь произвольную длину, но зачастую организованы в рамках прецедента (сеансы прецедента).

    Следствие. Заметим, что в этот перечень не включаются классы, реализующие окно, аплет, приложение, вид и документ. Такие классы не выполняют задачи, связанные с системными событиями. Они обычно получают сообщения и делегируют их контроллерам.

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

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

    Контроль состояния прецедента. Иногда необходимо удостовериться, что системные операции выполняются в некоторой определенной последовательности. Например, необходимо гарантировать, чтобы операция makePayment выполнялась только после операции EndSale, для чего необходимо накапливать информацию о последовательности событий. Для этой цели удобно использовать контроллер, особенно контроллер прецедента.

    Раздутый контроллер

    Плохо спроектированный класс контроллера имеет низкую степень зацепления: он выполняет слишком много обязанностей и является несфокусированным. Такой контроллер называется раздутым (bloated controller). Признаки раздутого контроллера таковы.

    В системе имеется единственный класс контроллера, получающий все системные сообщения, которых поступает слишком много. Такая ситуация зачастую возникает при использовании внешнего контроллера.

    Контроллер сам выполняет все задачи, не делегируя обязанности другим классам. Обычно это приводит к нарушению основных принципов шаблонов Information Expert и High Cohesion.

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

    Я хотел бы услышать твое мнение про паттерны поведения Надеюсь, что теперь ты понял что такое паттерны поведения и для чего все это нужно, а если не понял, или есть замечания,

    продолжение следует...

    Продолжение:


    Часть 1 2.4 Паттерны поведения
    Часть 2 2.4.7 Паттерн Chain Of Responsibility - 2.4 Паттерны поведения
    Часть 3 - 2.4 Паттерны поведения

    создано: 2014-10-05
    обновлено: 2021-03-13
    132816



    Рейтиг 9 of 10. count vote: 2
    Вы довольны ?:


    Поделиться:

    Найди готовое или заработай

    С нашими удобными сервисами без комиссии*

    Как это работает? | Узнать цену?

    Найти исполнителя
    $0 / весь год.
    • У вас есть задание, но нет времени его делать
    • Вы хотите найти профессионала для выплнения задания
    • Возможно примерение функции гаранта на сделку
    • Приорететная поддержка
    • идеально подходит для студентов, у которых нет времени для решения заданий
    Готовое решение
    $0 / весь год.
    • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
    • Вам предоставят готовое решение
    • Будет предоставлено в минимальные сроки т.к. задание уже готовое
    • Вы получите базовую гарантию 8 дней
    • Вы можете заработать на материалах
    • подходит как для студентов так и для преподавателей
    Я исполнитель
    $0 / весь год.
    • Вы профессионал своего дела
    • У вас есть опыт и желание зарабатывать
    • Вы хотите помочь в решении задач или написании работ
    • Возможно примерение функции гаранта на сделку
    • подходит для опытных студентов так и для преподавателей



    Комментарии


    Оставить комментарий
    Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
    To reply

    Объектно-ориентированное программирование ООП

    Термины: Объектно-ориентированное программирование ООП