1.91M
Category: programmingprogramming

Шаблоны проектирования (части 6-7)

1.

Лекция: Шаблоны проектирования (части 6-7)
1

2.

Содержание
6.1 Паттерн Декоратор;
6.2 Паттерн Макрокоманда;
6.3 Паттерн Одиночка;
6.4 Идиома Невиртуального интерфейса.
Паттерны Шаблонный метод и Curiously recurring;
6.5 Паттерн Транзакция;
6.6 Паттерны Фабричный метод и
Абстрактная фабрика
7.1 Что еще?
2

3.

6.1 Шаблон проектирования Декоратор
Декоратор (англ. Decorator) — структ

4.

6.1 Шаблон проектирования Декоратор

5.

6.1 Шаблон проектирования Декоратор

6.

6.1 Шаблон проектирования Декоратор. Пример

7.

6.1 Шаблон проектирования Декоратор. Пример

8.

6.1 Шаблон проектирования Декоратор. Пример

9.

6.1 Шаблон проектирования Декоратор. Пример

10.

6.1 Шаблон проектирования Декоратор. Пример
1. Какие паттерны применены на этом слайде кроме Декоратора?

11.

6.1 Шаблон проектирования Декоратор. Результаты
2. Какие результаты?
3. Как узнать тип и свойства объекта?
4. Насколько часто применим?
* 5. Декоратор — это стратегия? (рассуждать)
Есть много родственных паттернов. Макрокоманду разберем.
Цепочку ответственности — разобрать дома.

12.

6.2 Шаблон проектирования Макрокоманда
Это команда, но что будет если к ней применить декоратор?
* 6. Нарисовать диаграмму классов для паттерна Макрокоманда.

13.

6.3 Шаблон проектирования Одиночка
В Википедии можно найти
множество других реализаций
7. Что хотел показать авто

14.

6.3 Шаблон проектирования Одиночка. Примеры
Вернуться к примеру с Декоратором (там тоже есть Одиночка)

15.

6.3 Шаблон проектирования Одиночка. Реализации

16.

6.4 Идиома Невиртуального интерфейса.
Паттерн Шаблонный метод
class base {
public:
virtual ~base() {}
void show() { do_show(); }
void load(std::string const& filename) { do_load(filename); }
void save(std::string const& filename) { do_save(filename); }
protected:
virtual void do_show() = 0;
virtual void do_load(std::string const& filename) = 0;
virtual void do_save(std::string const& filename) = 0;
};
class derived : public base {
protected:
virtual void do_show() {}
virtual void do_load(std::string const& filename) {...}
virtual void do_save(std::string const& filename) {...}
};
8. Что дает такой подход?

17.

6.4 Идиома Невиртуального интерфейса.
Паттерн Шаблонный метод
1. Внутри невиртуальной функции вы можете осуществлять всяческие проверки, как до вы
2. Интерфейсы виртуальной и невиртуальной функции не обязаны совпадать. Открытая ф
3. Набор и интерфейс виртуальных функций может быть совершенно иным, нежели набор

18.

6.4 Идиома Невиртуального интерфейса.
Паттерн Шаблонный метод
Майерс: Правило 35: Рассмотрите альтернативы виртуальным функциям:
> Реализация паттерна««Шаблонный метод» с помощью идиомы невиртуального интерфе
> Реализация паттерна «Стратегия» посредством ...
Смысл ее (NVI) в том, чтобы обернуть открытыми невиртуальными функциями-членами вы

19.

class abstract {
public:
virtual ~abstract() {}
virtual void hello() = 0;
};
6.4 Идиома Невиртуального интерфейса.
Паттерн Curiously recurring
template <class T> class base : public abstract {
public:
virtual void hello() {
static_cast<T *>(this)->do_hello();
}
private:
void do_hello() {
std::cout << "base::hello()" << std::endl;
}
};
9. Что дает такой подход?
int main() {
typedef std::auto_ptr<abstract> abst_ptr;
abst_ptr a1(new left);
abst_ptr a2(new right);
a1->hello();
a2->hello();
return 0;
}
class left : public base<left> {
public:
void do_hello() { std::cout << "left::hello()" << std::endl; }
};
class right : public base<right> {};

20.

6.5 Паттерн Транзакция
typedef std::vector<std::string> file_list;
typedef std::vector<object_ptr> object_container;
void load_objects(file_list const &files, object_container &result) {
for (file_list::const_iterator it = files.begin(); it != files.end(); ++it) {
file_ptr fl = open_file(*it); // Может сгенерировать исключение
object_ptr obj = load_object(fl); // Может сгенерировать исключение
result.push_back(obj);
}
}
9. В чем проблема?
int main() {
10. Что если надо сохранить множест
file_list files;
object_container objects;
// ...
// Инициализация списка файлов
// ...
try {
load_objects(files, objects);
} catch (std::exception const &e) {
std::cout < < "Не могу загрузить объекты: " << e.what() << std::endl;
}
}

21.

6.5 Паттерн Транзакция
Следует разделять код на две части — «бросающую» обработку данных и «небросающее»
Реализуйте операции по сохранению изменений в системе как можно более локально и сд
Следует стремиться к тому, чтобы блок `catch` не содержал какого-то уникального кода по
Выполнить откат изменений при работе с глобальными сущностями (Одиночка) крайне сло
Существуют искусственные приемы обеспечения транзакционности; например — паттерн

22.

6.5 Паттерн Транзакция
class transaction {
public:
transaction() : incomplete(true) {}
~transaction() {
if (incomplete) {
revert();
}
}
template <class T> void begin(T &t) {
// в контейнер надо помещать
// обертку, умеющую revert()
params.push_back(t);
}
void commit() { incomplete = false; }
try {
transaction trn;
trn.begin(name);
trn.begin(bosom);
trn.begin(waist);
trn.begin(pelvis);
name = "Olga";
bosom = 102.4f;
waist = 59.3f;
pelvis = 92.3f;
// ...
// Здесь что-то происходит
// ...
throw std::runtime_error("Wife is coming!");
trn.commit();
} catch (std::exception const &) {
std::cout << "Hi, dear!" << std::endl;
}
protected:
bool incomplete;
param_container params;
//… функция revert() выполняет revert для всех элементов вектора
};

23.

6.5 Паттерн Транзакция. Результаты
1) Вы указываете список элементов транзакции в самом начале, и утверждаете внесенные
2) Даже глубинного копирования объекта не достаточно, чтобы последующий откат его зна
3) Старайтесь обеспечивать транзакционное поведение естественными описанием типов

24.

6.6 Паттерны Фабричный метод и Абстрактная фабрика
Допустим, есть классы игрушек, надо создавать объекты этих классов.
Фабричный метод предлагает делать так:
interface IToy {
string Name {
get;
set;
}
}
class Doll: IToy {
public string Name {
get;
set;
}
}
class TeddyBear: IToy {
public string Name {
get;
set;
}
}
11. Зачем так сложно?
abstract class ToyCreator {
public abstract IToy CreateToy(string name);
}
class DollCreator: ToyCreator {
public override IToy CreateToy(string name) {
return new Doll() {
Name = name
};
}
}
class TeddyBearCreator: ToyCreator {
public override IToy CreateToy(string name) {
return new TeddyBear() {
Name = name
};
}
}

25.

6.6 Паттерны Фабричный метод и Абстрактная фабрика
Основной мотив обоих шаблонов – создание новых объектов .
Также в обоих шаблонах звучит идея decoupling — отделения логики создания объектов от
Результаты применения фабричного метода:
Создание объектов-продуктов дистанцировано от клиента, инициирующего их создание.
●Весь алгоритм создания объектов – продуктов возложен на экземпляры классов – фабрик
●Расширяемость по типам продуктов.

26.

6.6 Паттерны Фабричный метод и Абстрактная фабрика
Основной мотив обоих шаблонов – создание новых объектов .
Также в обоих шаблонах звучит идея decoupling — отделения логики создания объектов от
Abstract Factory позволяет создавать базовый тип для создания групп ассоциированных об
12. Зачем это нужно? (примеры)

27.

6.6 Паттерны Фабричный метод и Абстрактная фабрика
if (race == Protos) {
return ProtosWarrior();
}
if (race == Zerg) {
return ZergWarrior();
}
// ...

28.

6.6 Паттерны Фабричный метод и Абстрактная фабрика
13. Так в чем разница?
(Чем Creator не Factory?)
abstract class ToyCreator {
public abstract IToy CreateToy(string name);
}
class DollCreator: ToyCreator {
public override IToy CreateToy(string name) {
return new Doll() {
Name = name
};
}
}
class TeddyBearCreator: ToyCreator {
public override IToy CreateToy(string name) {
return new TeddyBear() {
Name = name
};
}
}

29.

30.

31.

32.

7.1 Что еще?
Мы не рассмотрели множество паттернов. Часть из них широко известна и может приго
Другая часть полезна для понимания общих идей (Джейсон Мак-Колм Смит Элем
Наконец, ряд паттернов применяется в конкретных предметных областях. Мы их почти
Паттерны связаны друг с другом. Просто так взять и разобраться не выйдет.
Паттерны — это:
- чисто инженерная практика;
- способ улучшить код;
- способ сделать код понятнее (стандартнее);
- элемент документации.

33.

7.1 Что еще?
Хорошее понимание сути каждго паттерна позволяет писать код проще (см. примеры «
Многие паттерны взаимозаменяемые. Встает проблема выбора подходящего паттерна
Влиссидес Джон. Применение шаблонов проектирования. Дополнительные
Неудачное применение паттерна — это плохо.
17) Какие паттерны особенно плохие?

34.

7.1 Что еще?
Существуют антипаттерны:
- Copy and paste;
- Spaghetti - расползание кода на одном «этаже» программы;
- Golden hammer (золотой молот) - применение какого-то конкретного паттерна для реш
- Hard code, Magic numbers, Magic strings;
- Reinventing the wheel;
- Cargo cult programming — это использование паттернов без четкого понимания того, д
- Blob — класс, на который возложено слишком много обязанностей;
- Programming by permutation — это программирование методом подбора;
«Interface bloat» — слишком сильно «раздутый» интерфейс, определяющий слишком м
Lava flow — отказ от рефакторинга или замены неудачного решения (менеджмент);
Premature optimization и Premature pessimization;
Exception handling - реализация нормальной логики работы программы с помощью мех

35.

7.1 Что еще?
*18) Построить диаграмму зависимостей между всеми известными вам паттернами, испол
Чем больше — тем лучше.
Лучше мало, но правильно.
English     Русский Rules