- •Лабораторная работа №4 Шаблоны проектирования
- •Теоретические сведения
- •Отношения между классами. На диаграммах классов языка uml
- •Суть паттерна
- •Решение
- •Адаптер объектов
- •Адаптер классов
- •Адаптер классов не нуждается во вложенном объекте, так как он может одновременно наследовать и часть существующего класса, и часть сервиса.
- •Фасад (Facade)
- •Концептуальный пример
- •Program.Cs:
- •Output.Txt: Результат выполнения
- •Изолирует клиентов от компонентов подсистемы Уменьшая тем самым число объектов, с которыми клиентам приходится иметь дело, упрощая работу с подсистемой.
- •Позволяет ослабить связанность между подсистемой и ее клиентами.
- •Фасад не исключает возможности приложениям напрямую обращаться к классам подсистемы, если это необходимо.
- •Заместитель (Proxy)
- •3. Локальный запуск сервиса (удалённый прокси). Когда настоящий сервисный объект находится на удалённом сервере.
- •Концептуальный пример
- •Декоратор (Decorator)
- •// Объект
- •} //Ptr2 выходит из области видимости, но объект не //освобождается, потому что есть ptr, который по-прежнему //ссылается на него } //ptr выходит из области видимости, и объект уничтожается
- •Пример на языке c#
- •Порождающие шаблоны Абстрактная фабрика (Abstract Factory)
- •1. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы.
- •3. Таким образом, еще раз - предоставляет интерфейс для создания семейств, связанных между собой, или зависимых объектов.
- •Клиент пользуется только интерфейсами, заданными в классах «Абстрактная фабрика» и «Абстрактный продукт».
- •Фабричный метод (Factory Method)
- •Void info() {
- •Void info() {
- •Void info() {
- •Int main()
- •Одиночка (Singleton) Суть паттерна
- •If(!p_instance)
- •Поведенческие шаблоны Стратегия (Strategy)
- •Стратегии построения пути.
- •Структура
- •Концептуальный пример
- •Program.Cs: Пример структуры паттерна
- •Output.Txt: Результат выполнения
- •Void useStrategy(void)
- •Void setStrategy(Strategy* o)
- •Int main(int /*argc*/, char* /*argv*/[])
- •Наблюдатель (Observer) Суть паттерна
- •Решение
- •Структура
- •Шаги реализации
- •Концептуальный пример
- •Program.Cs: Пример структуры паттерна
- •// Random.Next(…) - Метод, возвращает случайное целое число //в указанном диапазоне.
- •Output.Txt: Результат выполнения
- •Использование паттерна Observer
- •Команда (Command)
- •Структура
- •Output.Txt: Результат выполнения
- •Задания для лабораторной работы
Команда (Command)
Команда — поведенческий шаблон проектирования, используемый при объектно-ориентированном программировании, представляющий действие.
Объект Команда заключает в себе само действие и его параметры.
Паттерн обеспечивает обработку команды в виде объекта, что позволяет сохранять её, передавать в качестве параметра методам, а также возвращать её в виде результата, как и любой другой объект.
Паттерн Command преобразовывает запрос на выполнение действия в отдельный объект команду.
Такая инкапсуляция позволяет передавать эти действия другим функциям и объектам в качестве параметра, приказывая им выполнить запрошенную операцию.
Команда – это объект, поэтому над ней допустимы любые операции, что и над объектом.
Интерфейс Командного объекта определяется абстрактным базовым классом Command и в самом простом случае имеет единственный метод execute().
Производные классы определяют получателя запроса (указатель на объект получатель) и необходимую для выполнения операцию (метод этого объекта).
Метод execute() подклассов Command просто вызывает нужную операцию получателя.
В паттерне Command может быть до трех участников:
● Клиент, создающий экземпляр Командного объекта.
● Инициатор запроса, использующий Командный объект.
● Получатель запроса.
- Сначала Клиент создает объект ConcreteCommand, конфигурируя его получателем запроса.
- Этот объект также доступен Инициатору.
- Инициатор использует его при отправке запроса, вызывая метод execute().
- Этот алгоритм напоминает работу функции обратного вызова в процедурном программировании – функция регистрируется, чтобы быть вызванной позднее.
- Паттерн Command отделяет объект, инициирующий операцию, от объекта, который знает, как ее выполнить.
- Единственное, что должен знать Инициатор, это как отправить команду.
- Это придает системе гибкость: позволяет осуществлять динамическую замену команд, использовать сложные, составные команды, осуществлять отмену операций.
Тип: поведенческий
Назначение: для обработки команды в виде объекта
Родственные шаблоны: Компоновщик, Хранитель, Прототип, Одиночка
Пример:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Document
{
vector<string> data;
public:
void Insert( int line, const string & str )
{
if ( line <= data.size() )
data.insert( data.begin() + line, str );
else
cout << "Error!" << endl;
}
void Remove( int line )
{
if( !( line>data.size() ) )
data.erase( data.begin() + line );
else
cout << "Error!" << endl;
}
string & operator [] ( int x )
{
return data[x];
}
void Show()
{
for( int i = 0; i<data.size(); ++i )
{
cout << i + 1 << ". " << data[i] << endl;
}
}
};
class Command
{
protected:
Document * doc;
public:
virtual void Execute() = 0;
virtual void unExecute() = 0;
void setDocument( Document * _doc )
{
doc = _doc;
}
};
class InsertCommand : public Command
{
int line;
string str;
public:
InsertCommand( int _line, const string & _str ): line( _line ), str( _str ) {}
void Execute()
{
doc->Insert( line, str );
}
void unExecute()
{
doc->Remove( line );
}
};
class Receiver
{
vector<Command*> DoneCommands;
Document doc;
Command* command;
public:
void Insert( int line, string str )
{
command = new InsertCommand( line, str );
command->setDocument( &doc );
command->Execute();
DoneCommands.push_back( command );
}
void Undo()
{
if( DoneCommands.size() == 0 )
{
cout << "There is nothing to undo!" << endl;
}
else
{
command = DoneCommands.back();
DoneCommands.pop_back();
command->unExecute();
// Don't forget to delete command!!!
delete command;
}
}
void Show()
{
doc.Show();
}
};
int main()
{
char s = '1';
int line, line_b;
string str;
Receiver res;
while( s!= 'e' )
{
cout << "What to do: \n1.Add a line\n2.Undo last command" << endl;
cin >> s;
switch( s )
{
case '1':
cout << "What line to insert: ";
cin >> line;
--line;
cout << "What to insert: ";
cin >> str;
res.Insert( line, str );
break;
case '2':
res.Undo();
break;
}
cout << "$$$DOCUMENT$$$" << endl;
res.Show();
cout << "$$$DOCUMENT$$$" << endl;
}
}
Команда и Стратегия похожи по духу, но отличаются масштабом и применением:
Команду используют, чтобы превратить любые разнородные действия в объекты. Параметры операции превращаются в поля объекта. Этот объект теперь можно логировать, хранить в истории для отмены, передавать во внешние сервисы и так далее.
С другой стороны, Стратегия описывает разные способы произвести одно и то же действие, позволяя взаимозаменять эти способы в каком-то объекте контекста.
