Upload
dima-dzuba
View
708
Download
1
Embed Size (px)
Citation preview
Паттерны создания объектов
Паттерны проектированияСоздание объектовОписывают способы как можно создавать объекты в программе.
Борется с основным видом зависимости между модулями – знанием о существовании модуля и месте расположения.
Самое серьезное препятствие лежит в жестко зашитой в код информации о том, какие классы инстанцируются.
С помощью порождающих паттернов можно различными способами избавиться от явных ссылок на конкретные классы из кода.
Паттерны:◦ Abstract Factory◦ Builder◦ Factory Method◦ Prototype◦ Singleton
2
Abstract Factory◦ Описание задачи
Требуется иметь интерфейс для создания серии однотипных объектов.
◦ Описание решения
Создание отдельного класса отвечающего за создание экземпляров объектов.
◦ Когда применять
Можно выделить группы схожих объектов. Т.е. в одном случае мы создаем один набор объектов (одной фабрикой) в другом случае другой набор объектов (другой фабрикой)
◦ Пример
Интерфейс пользователя с набором «скинов». Т.е. набор различных по отображению интерфейсов но с одинаковой функциональностью.
Доступ к базе данных (когда для разных СУБД есть разные объекты доступа)
3
Abstract FactoryAbstractFactory - абстрактная фабрика:объявляет интерфейс для операций, создающих абстрактные объекты-продукты;
ConcreteFactory - конкретная фабрика:реализует операции, создающие конкретные объекты-продукты;
AbstractProduct - абстрактный продукт:объявляет интерфейс для типа объекта-продукта;
ConcreteProduct - конкретный продукт:определяет объект-продукт, создаваемый соответствующей конкретной фабрикой и реализует интерфейс Abstract Product;
Client - клиент:пользуется исключительно интерфейсами, которые объявлены в классах AbstractFactory и AbstractProduct.
4
Abstract FactoryCPP_Examples08
MazeFactory *factory = new MazeFactory();
//MazeFactory *factory = new ConcreteFactory();
Maze *maze = factory->MakeMaze();
Room *r1 = factory->MakeRoom();
Room *r2 = factory->MakeRoom();
Door *d = factory->MakeDoor(r1,r2);
Wall *w1 = factory->MakeWall();
r1->AddWall(w1);
maze->AddRoom(r1);
maze->AddRoom(r2);
5
builder◦ Описание задачи
Необходимо конструировать сложные объекты. При этом объекты со схожей конструкцией могут создаваться из разных объектов.
◦ Описание решенияВыделяется специальный объект, реализующий алгоритм создания сложного объекта. Создаются объекты, для создания частей составного объекта.
◦ Когда применять
Когда есть набор сложных объектов, состоящих из однотипных частей и имеющих схожий алгоритм создания.
◦ Пример
Преобразование форматов, когда нужно применить последовательно серию преобразований. Например при переводе текста из одного формата в другой мы последовательно применяем наборы преобразований параграфов, слов, шрифтов …
6
ПримерCPP_Examples09
//Builder *builder = new Builder();
Builder *builder = new ConcreteBuilder();
Director *director = new Director();
Maze *maze;
maze = director->Construct(builder);
delete director;
delete builder;
delete maze;
7
Паттерны проектированияcоздание объектов / Factory Method
◦ Описание задачиВнутри метода класса нам нужно создавать экземпляр другого класса. При этом в наследниках, нам возможно понадобится создавать другие классы.
◦ Описание решенияКонструктор класса вызывается в специальном методе, который может быть переопределен в наследнике.
◦ Когда применятьХорошо все вызовы new оформлять в виде отдельных методов, где это возможно.
◦ ПримерПриложение может использовать различные библиотеки для доступа к базе данных. Создание экземпляра объекта-библиотеки может определяться конфигурацией.
8
Factory MethodДве основных разновидности паттерна.
◦ Во-первых, это случай, когда класс Сгeator'является абстрактным и не содержит реализации объявленного в нем фабричного метода.
◦ Вторая возможность: Creator – конкретный класс, в котором по умолчанию есть реализация фабричного метода. Редко, но встречается и абстрактный класс, имеющий реализацию по умолчанию;
Параметризованные фабричные методы.
Это еще один вариант паттерна, который позволяет фабричному методу создавать разные виды продуктов. Фабричному методу передается параметр, который идентифицирует видсоздаваемого объекта. Все объекты, получающиеся с помощью фабричного метода, разделяют общий интерфейс Product..
9
ПримерCP_Example10
//Creator *creator = new Creator();
Creator *creator = new CreatorChild();
MyObject* obj = creator->factoryMethod();
obj->Foo();
delete obj;
delete creator;
10
Prototype
◦ Описание задачиНеобходимо создавать объект «по образцу».
◦ Описание решенияУ объектов, требующих копирование создается метод Clone дублирующий объект.
◦ Когда применятьМного объектов требующих создание по образцу или жесткие требования к модифицируемости программы.
◦ ПримерГрафический редактор, где на палитре «инструментов» размещаются
объекты. При помещении из в рабочее поле создаются копии объектов с палитры.
11
PrototypeВарианты реализации
◦ использование диспетчера прототипов.
◦ реализация операции Clone.
Преимущества◦ добавление и удаление продуктов во время выполнения.
◦ спецификация новых объектов путем изменения значений.
Недостатки◦ Основной недостаток паттерна прототип заключается в том, что каждый подкласс класса Prototype
должен реализовывать операцию Clone, а это далеко не всегда просто. Например, сложно добавить операцию Clone, когда рассматриваемые классы уже существуют.
◦ Проблемы возникают и в случае, если во внутреннем представлении объекта есть другие объекты или наличествуют круговые ссылки
12
ПримерCPP_Examples11
#include <iostream>
#include "ConcretePrototype1.h"
#include "ConcretePrototype2.h"
int main(int argc, char* argv[]){
Prototype *prt1 = new ConcretePrototype1();
Prototype *prt2 = new ConcretePrototype2();
Prototype *clone = prt2->Clone();
delete prt1;
delete prt2;
delete clone;
return 0;}
13
Двойная диспечеризацияVisitor
◦ Описание задачи
Есть сложная структура объектов, необходимо со всеми элементами проделать операции (отличающиеся для разных типов элементов).
◦ Описание решения
Создается иерархия объектов с алгоритмами (Visitor). В элементах создается метод, который реализует вызов алгоритма для конкретного типа элемента.
◦ Когда применять
Операция зависит от типа элемента.
◦ Пример
Анализ динамических структур данных. Разные анализаторы реализуют проверку различных правил.
14
Когда применять?◦ в структуре присутствуют объекты многих
классов с различными интерфейсами и вы хотите выполнять над ними операции, зависящие от конкретных классов;
◦ над объектами, входящими в состав структуры, надо выполнять разнообразные, не связанные между собой операции и вы не хотите ≪засорять≫ классы такими операциями. Посетитель позволяет объединить родственные операции, поместив их в один класс.
◦ классы, устанавливающие структуру объектов, изменяются редко, но новые операции над этой структурой добавляются часто. При изменении классов, представленных в структуре, нужно будет переопределить интерфейсы всех посетителей, а это может вызвать затруднения. Поэтому если классы меняются достаточно часто, то лучше определить операции прямо в них.
15
Примерcpp_examples15class Visitor
{
public:
Visitor(void);
virtual void AddColor(ElementA*);
virtual void AddSize(ElementB*);
~Visitor(void);
};
class Element
{
public:
Element(void);
~Element(void);
virtual void Accept(Visitor* visitor) =
0;
};
16
ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ
ExceptionsДля реализации механизма обработки исключений в язык Си++ введены следующие три ключевых (служебных) слова:
1. try (контролировать)
2. catch (ловить)
3. throw (генерировать, порождать, бросать, посылать, формировать).
ExceptionИсключение это:
1. Объект, наследник класса std::exception (#include <exception>)
2. Событие, прерывающее обработку программы.
Под прерыванием мы понимаем, что срабатывание исключение, аналогично срабатыванию оператора return.
Но есть существенное отличие: return возвращает результат в то место, где вызвали функцию. Исключение возвращает объект исключения только в те места, где его явно ловят (catch)! И только если исключение сработало (throw) в месте где мы его контролируем (try)!
Если исключение не поймать (catch) то оно будет прерывать работу функций, поднимаясь вверх по стеку вызова, пока не остановит программу.
Try / CatchСлужебное слово try позволяет выделить в любом месте исполняемого текста программы так называемый контролируемый блок:
try {
операторы
операторы
} catch (Тип_исключения1 имя){
операторы
} catch (Тип_исключения2 имя){
операторы
}
ExceptionsCPP_Examples13
try{
throw MyException(100);
}catch(MyException& ex){
std::cout << "MyException in Proc2: " << ex.A << "\n";
std::exception_ptr currentException = std::make_exception_ptr(ex);
std::rethrow_exception(currentException);
}
catch(...){
std::exception_ptr currentException = std::current_exception();
}
ExceptionПомни, что в блоке catch могут возникать свои исключения!
Если в блоке catch идет высвобождение ресурсов (удаление объектов, закрытие дескрипторов файлов) то их надо самих помещать в еще один вложенный блок try/catch.