22
Паттерны создания объектов

Объектно-Ориентированное Программирование на C++, Лекция 5

Embed Size (px)

Citation preview

Page 1: Объектно-Ориентированное Программирование на C++, Лекция 5

Паттерны создания объектов

Page 2: Объектно-Ориентированное Программирование на C++, Лекция 5

Паттерны проектированияСоздание объектовОписывают способы как можно создавать объекты в программе.

Борется с основным видом зависимости между модулями – знанием о существовании модуля и месте расположения.

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

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

Паттерны:◦ Abstract Factory◦ Builder◦ Factory Method◦ Prototype◦ Singleton

2

Page 3: Объектно-Ориентированное Программирование на C++, Лекция 5

Abstract Factory◦ Описание задачи

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

◦ Описание решения

Создание отдельного класса отвечающего за создание экземпляров объектов.

◦ Когда применять

Можно выделить группы схожих объектов. Т.е. в одном случае мы создаем один набор объектов (одной фабрикой) в другом случае другой набор объектов (другой фабрикой)

◦ Пример

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

Доступ к базе данных (когда для разных СУБД есть разные объекты доступа)

3

Page 4: Объектно-Ориентированное Программирование на C++, Лекция 5

Abstract FactoryAbstractFactory - абстрактная фабрика:объявляет интерфейс для операций, создающих абстрактные объекты-продукты;

ConcreteFactory - конкретная фабрика:реализует операции, создающие конкретные объекты-продукты;

AbstractProduct - абстрактный продукт:объявляет интерфейс для типа объекта-продукта;

ConcreteProduct - конкретный продукт:определяет объект-продукт, создаваемый соответствующей конкретной фабрикой и реализует интерфейс Abstract Product;

Client - клиент:пользуется исключительно интерфейсами, которые объявлены в классах AbstractFactory и AbstractProduct.

4

Page 5: Объектно-Ориентированное Программирование на C++, Лекция 5

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

Page 6: Объектно-Ориентированное Программирование на C++, Лекция 5

builder◦ Описание задачи

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

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

◦ Когда применять

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

◦ Пример

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

6

Page 7: Объектно-Ориентированное Программирование на C++, Лекция 5

Пример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

Page 8: Объектно-Ориентированное Программирование на C++, Лекция 5

Паттерны проектированияcоздание объектов / Factory Method

◦ Описание задачиВнутри метода класса нам нужно создавать экземпляр другого класса. При этом в наследниках, нам возможно понадобится создавать другие классы.

◦ Описание решенияКонструктор класса вызывается в специальном методе, который может быть переопределен в наследнике.

◦ Когда применятьХорошо все вызовы new оформлять в виде отдельных методов, где это возможно.

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

8

Page 9: Объектно-Ориентированное Программирование на C++, Лекция 5

Factory MethodДве основных разновидности паттерна.

◦ Во-первых, это случай, когда класс Сгeator'является абстрактным и не содержит реализации объявленного в нем фабричного метода.

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

Параметризованные фабричные методы.

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

9

Page 10: Объектно-Ориентированное Программирование на C++, Лекция 5

ПримерCP_Example10

//Creator *creator = new Creator();

Creator *creator = new CreatorChild();

MyObject* obj = creator->factoryMethod();

obj->Foo();

delete obj;

delete creator;

10

Page 11: Объектно-Ориентированное Программирование на C++, Лекция 5

Prototype

◦ Описание задачиНеобходимо создавать объект «по образцу».

◦ Описание решенияУ объектов, требующих копирование создается метод Clone дублирующий объект.

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

◦ ПримерГрафический редактор, где на палитре «инструментов» размещаются

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

11

Page 12: Объектно-Ориентированное Программирование на C++, Лекция 5

PrototypeВарианты реализации

◦ использование диспетчера прототипов.

◦ реализация операции Clone.

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

◦ спецификация новых объектов путем изменения значений.

Недостатки◦ Основной недостаток паттерна прототип заключается в том, что каждый подкласс класса Prototype

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

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

12

Page 13: Объектно-Ориентированное Программирование на C++, Лекция 5

Пример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

Page 14: Объектно-Ориентированное Программирование на C++, Лекция 5

Двойная диспечеризацияVisitor

◦ Описание задачи

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

◦ Описание решения

Создается иерархия объектов с алгоритмами (Visitor). В элементах создается метод, который реализует вызов алгоритма для конкретного типа элемента.

◦ Когда применять

Операция зависит от типа элемента.

◦ Пример

Анализ динамических структур данных. Разные анализаторы реализуют проверку различных правил.

14

Page 15: Объектно-Ориентированное Программирование на C++, Лекция 5

Когда применять?◦ в структуре присутствуют объекты многих

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

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

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

15

Page 16: Объектно-Ориентированное Программирование на C++, Лекция 5

Пример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

Page 17: Объектно-Ориентированное Программирование на C++, Лекция 5

ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ

Page 18: Объектно-Ориентированное Программирование на C++, Лекция 5

ExceptionsДля реализации механизма обработки исключений в язык Си++ введены следующие три ключевых (служебных) слова:

1. try (контролировать)

2. catch (ловить)

3. throw (генерировать, порождать, бросать, посылать, формировать).

Page 19: Объектно-Ориентированное Программирование на C++, Лекция 5

ExceptionИсключение это:

1. Объект, наследник класса std::exception (#include <exception>)

2. Событие, прерывающее обработку программы.

Под прерыванием мы понимаем, что срабатывание исключение, аналогично срабатыванию оператора return.

Но есть существенное отличие: return возвращает результат в то место, где вызвали функцию. Исключение возвращает объект исключения только в те места, где его явно ловят (catch)! И только если исключение сработало (throw) в месте где мы его контролируем (try)!

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

Page 20: Объектно-Ориентированное Программирование на C++, Лекция 5

Try / CatchСлужебное слово try позволяет выделить в любом месте исполняемого текста программы так называемый контролируемый блок:

try {

операторы

операторы

} catch (Тип_исключения1 имя){

операторы

} catch (Тип_исключения2 имя){

операторы

}

Page 21: Объектно-Ориентированное Программирование на C++, Лекция 5

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();

}

Page 22: Объектно-Ориентированное Программирование на C++, Лекция 5

ExceptionПомни, что в блоке catch могут возникать свои исключения!

Если в блоке catch идет высвобождение ресурсов (удаление объектов, закрытие дескрипторов файлов) то их надо самих помещать в еще один вложенный блок try/catch.