Главная страница
Навигация по странице:

  • Abstract Factory

  • Template Method

  • Язык текстовых шаблонов T4. 1.Паттерны проектирования 12.Язык текстовых шаблонов T4. 5 Основные понятия

  • Зачем это надо

  • Блок расширения

  • Паттерны проектирования Шаблон T4. Паттерны проектирования


    Скачать 35.46 Kb.
    НазваниеПаттерны проектирования
    Дата19.12.2022
    Размер35.46 Kb.
    Формат файлаdocx
    Имя файлаПаттерны проектирования Шаблон T4.docx
    ТипЗадача
    #851801




    1. Паттерны проектирования

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

    Паттерны проектирования – это не то же самое, что связанные списки или хэш-таблицы, которые можно реализовать в виде класса и повторно использовать без каких бы то ни было модификаций. Но это и не сложные, предметно-ориентированные решения для целого приложения или подсистемы.

    Под паттернами проектирования понимается описание взаимодействия объектов и классов, адаптированных для решения общей задачи проектирования в конкретном контексте.

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

    Паттерны по своей цели (назначению) подразделяются на:

    • порождающие паттерны;

    • структурные паттерны;

    • паттерны поведения.

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

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

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

    Основные паттерны:

    • «Одиночка» (Singleton);

    • «Абстрактная фабрика» (Abstract Factory);

    • «Фасад» (Facade);

    • «Команда» (Command);

    • «Прототип» (Prototype);

    • «Стратегия» (Strategy);

    • «Приспособленец» (Flyweight);

    • «Шаблонный метод» (Template Method)


    Singleton

    Является порождающим паттерном. Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.

    Используется, когда:

    • должен быть ровно один экземпляр некоторого класса, легко доступный всем клиентам;

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


    Abstract Factory

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

    Используется, когда:

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

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

    • система должна конфигурироваться одним из семейств составляющих ее объектов;

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


    Facade

    Является структурным паттерном. Предоставляет унифицированный интерфейс вместо набора интерфейсов не­которой подсистемы. Facade определяет интерфейс более высокого уровня, кото­рый упрощает использование подсистемы

    Используется, когда:

    • необходимо предоставить простой интерфейс к сложной подсистеме. Часто подсистемы усложняются по мере развития. Применение большинства паттернов приводит к появлению меньших классов, но в большем количестве. Такую подсистему проще повторно использовать и настраивать под конкретные нужды, но вместе с тем применять подсистему без настройки становится труднее. Facade предлагает некоторый вид системы по умолчанию, устраивающий большинство клиентов. И лишь те объекты, которым нужны более широкие возможности настройки, могут обратиться напрямую к тому, что находится за фасадом;

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

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


    Command

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

    Используется, когда:

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

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

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

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

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


    Prototype

    Является порождающим паттерном. Задает виды создаваемых объектов с помощью экземпляра-прототипа и создает новые объекты путем копирования этого прототипа.

    Используется, когда:

    • система не должна зависеть от того, как в ней создаются, компонуются и представляются продукты;

    • инстанцируемые классы определяются во время выполнения, например, с помощью динамической загрузки;

    • для того чтобы избежать построения иерархий классов или фабрик, параллельных иерархии классов продуктов;

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


    Strategy

    Является паттерном поведения. Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Strategy позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются.

    Используется, когда:

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

    • необходимо иметь несколько разных вариантов алгоритма. Например, можно определить два варианта алгоритма, один из которых требует больше времени, а другой – больше памяти. Стратегии разрешается применять, когда варианты алгоритмов реализованы в виде иерархии классов;

    • в алгоритме содержатся данные, о которых клиент не должен «знать». Используйте паттерн стратегия, чтобы не раскрывать сложные, специфичные для алгоритма структуры данных;

    • в классе определено много поведений, что представлено разветвленными условными операторами. В этом случае проще перенести код из ветвей в отдельные классы стратегий.


    Flyweight

    Является порождающим паттерном. Использует разделение для эффективной поддержки множества мелких объектов.

    Используется, когда выполнены все ниже перечисленные условия (максимальная эффективность применения данного паттерна):

    • в приложении используется большое число объектов;

    • из-­за этого накладные расходы на хранение высоки;

    • большую часть состояния объектов можно вынести вовне;

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

    • приложение не зависит от идентичности объекта. Поскольку объекты-приспособленцы могут разделяться, то проверка на идентичность возвратит «истину» для концептуально различных объектов.


    Template Method

    Является паттерном поведения. Определяет основу алгоритма и позволяет подклассам пе­реопределить некоторые шаги алгоритма, не изменяя его структуру в целом.

    Используется, когда:

    • необходимо однократно использовать инвариантные части алгоритма, оставляя реализацию изменяющегося поведения на усмотрение подклассов;

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

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

    Пример области и паттернов:

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

    • отдать заказ;

    • узнать о его состоянии готовности;

    • забрать заказ.

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

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

    Стоит уточнить, что предметной областью могут быть также некоторые аспекты программирования. Например, разработка своей библиотеки, взаимодействие извне с некоторой формой GUI и пр.
    Литература

    Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приемы объектно-ориентированного проектирования. Паттерны проектирования. – СПб.: Питер, 2020. – 368 с.: ил. – (Серия «Библиотека программиста»).


    1. Язык текстовых шаблонов T4.

    1.Паттерны проектирования 1

    2.Язык текстовых шаблонов T4. 5

    Основные понятия

    Стандарт текстовых шаблонов Т4 (Text Template Transformation Toolkit) – это механизм, позволяющий генерировать различные тексты на основе задающихся правил. Генерироваться могут как простые тексты (как содержание договоров), так и исходные коды программ высокого и низкого уровней – всё зависит лишь от умения и фантазии разработчика.

    Зачем это надо: создание текстовых файлов, поддающиеся чёткому алгоритму, может быть раздражительным – особенно, если часто вносятся мелкие правки в содержание, из-за которых приходится проходить весь файл и вносить правки. Для решения такой проблемы можно использовать шаблон Т4, который будет просто пересоздавать файл. Достаточно внести пару правок в шаблон и весь результирующий файл будет новеньким, удобно. Особенно это касается, в частности, SQL запросов для работы с БД и авто-тестирование. Зачем писать скрипты для тестирования или обновления БД каждый раз, или править какие-то мелкие моменты (вроде версии или названия переменных) вручную, когда можно сгенерировать сразу все запросы и скрипты одной кнопкой? В этом и состоит смысл и предназначение – избавление от рутинной работы, экономия времени, облегчение жизни.

    Упрощённо этот механизм выглядит так (в примере псевдокод):

    Шаблон:

    (Сделать 3 раза:

    Напечатать «Слово»

    Добавить отступ в начале строки

    Напечатать «Всё»)

    Результат:

    Слово

    Слово

    Слово

    Всё

    Не вдаваясь в подробности, процесс выглядит следующим образом: разработчик пишет содержание шаблона, используя любой из допустимых (поддерживаемых) языков программирования (на данный момент поддерживается большинство высокоуровневых) и использует генератор, который, потребляя такой шаблон, выдаёт желаемый файл нужного разрешения. Microsoft, как одни из авторов этой технологии, ещё с 2005 года включили генератор и поддержку этих шаблонов в стандартный набор Visual Studio. Соответственно в этой среде разработки работа с такими шаблонами максимально простая – достаточно составить шаблон так, как нам хочется, далее просто сохранить его – в этот момент активируется генератор Т4, который сразу попытается получить результирующий файл из нашего шаблона. Если не получится – он укажет на возможные ошибки.

    Основные функциональные блоки шаблона Т4 - управление, выражение, расширение.

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

    Следует отметить следующее:

    - класс одного шаблона можно добавлять к другом шаблоне, это вложение шаблонов (так делать можно, но в вариантах задания этой л.р. не присутствует);

    - класс обладает множеством полей и методов, некоторые из которых значительно упрощают написания шаблона, некоторые из них будут приведены ниже и должны использоваться при выполнении задания;

    - класс можно расширять, добавляя в него свои методы и поля (и даже собственные классы, вложенные в главный) по желанию.

    Полезные методы любого класса шаблона:

    - вывод s, не переводя «каретку» на следующую строку;

    - вывод s, с переводом «каретки»

    где s – строка или число, выводимое в результирующий файл;

    - добавление отступа к любой выводимой строке;

    - удаление отступа у выводимой строки;

    - удаление всего набора отступов.

    Отступы работают по механизму стека и следуют один за другим.


    Блок управления

    Блок управления одержит в себе код, который отрабатывает согласно правилам выбранного ЯП. В нём работа идёт как при обычном программировании – можно задавать переменные, использовать ветвления, циклы и прочее.

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

    Один и тот же блок управления может располагаться в нескольких открывающихся и закрывающихся скобках, например:

    ШАБЛОН:

    <#

    Int I = 0

    While (I < 5)

    {

    #>

    Привет!

    <#

    I++;

    }

    #>
    РЕЗУЛЬТАТ:

    Привет!

    Привет!

    Привет!
    Код цикла в примере «разрывается» посередине строкой, которую надо выводить 100 раз, однако генератор Т4 способен анализировать такие «разрывы» и связывать исполнение кода сквозь множество блоков управления друг за другом. Итогом будет вывод 100 раз строчки «Привет!» в результирующем файле.

    Можно сказать, что все блоки управления <# CODE #> при генерации превращаются в один большой исполняемый код и это надо иметь в виду.


    Блок выражения

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

    Содержится в скобках <#= VALUE #>.

    Обратите внимание на знак «=» в открывающей скобке блока. Пример:

    ШАБЛОН:

    <#

    int firstVar = 10;

    string secondVar = "bigger";

    string thirdVar = "lesser";

    const int compareToVariable_1 = 5;

    #>
    А теперь используем блок выражения для вывода
    Сравниваем с константой <#= compareToVariable_1 #>

    Результат = <#= firstVar > compareToVariable_1 ? secondVar : thirdVar #>
    РЕЗУЛЬТАТ:

    А теперь используем блок выражения для вывода

    Сравниваем с константой 5

    Результат = bigger
    Как видно, в данном примере сначала используется блок управления для задания некоторых переменных, а затем используются два блока выражения для вывода. В первый блок выражения просто подставляется значение константы, а во втором присутствует тернарный оператор (a) ? b : c, который работает ровно как if (a) then b else c. В конце концов, в блоке выражения должно оказаться какое-то выражение (например, формула из чисел) или переменная, которая будет подставлена вместо всего этого блока в результирующий файл.


    Блок расширения

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

    Содержится в скобках <#+ EXTENTION #>, вновь обращаем внимание на символ «+» при открытии блока.

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




    написать администратору сайта