Top Banner
Модуль 4 : Дополнительные темы объектно-ориентированного программирования. Темы лекции : Отношения между классами. Порождающие шаблоны проектирования. Практическое задание : Порождающие шаблоны. Тренер: Игорь Шкулипа, к.т.н. C++ Базовый. Занятие 16
57

C++ Базовый. Занятие 16.

Mar 21, 2017

Download

Education

Igor Shkulipa
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: C++ Базовый. Занятие 16.

Модуль 4: Дополнительные темы объектно-ориентированного программирования.

Темы лекции: Отношения между классами. Порождающие шаблоны проектирования.

Практическое задание: Порождающие шаблоны.

Тренер: Игорь Шкулипа, к.т.н.

C++ Базовый. Занятие 16

Page 2: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 2

Отношения между классами в ООП

Page 3: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 3

Ассоциация

Ассоциация - самый слабый вид связи. Обычно ассоциациявозникает, когда один класс вызывает метод другого илиесли при вызове метода в качестве аргумента передаётсяобъект другого класса.

Page 4: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 4

Агрегация

Агрегация (присоединение, включение) - агрегирование илисоединение частей. Например, когда класс содержит поле –объект другого класса.

Page 5: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 5

Композиция

Композиция классов - более сильная связь между классами, чемагрегация.

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

Page 6: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 6

Наследование

Наследование – это отношение между классами, при которомкласс-наследник использует поля и методы родительскогокласса.

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

Класс, производный от суперкласса, называется подклассом,производным или дочерним классом

Page 7: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 7

Формы наследования

В подклассе структура и поведение исходного суперкласса могутдополняться, переопределяться или ограничиваться.

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

1. Специализация

2. Спецификация

3. Обобщение

4. Расширение

5. Ограничение

6. Конструирование

7. Варьирование

8. Комбинирование

Page 8: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 8

Специализация

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

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

Поведение базового класса, в основном, переопределяется.

специализация

Page 9: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 9

Спецификация

Родительский класс описывает поведение, которое реализуется вдочернем классе, но оставлено нереализованным вродительском

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

спецификацияспецификацияспецификация

Page 10: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 10

Обобщение

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

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

обобщение

Page 11: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 11

Расширение

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

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

расширение

Page 12: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 12

Ограничение

Дочерний класс ограничивает использование некоторых методовродительского класса.

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

ограничениеограничение

Page 13: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 13

Конструирование

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

Между дочерним и родительским классами отсутствует отношение«is-a» или «быть экземпляром», то есть дочерний класс не являетсяболее специализированной формой родительского класса.

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

Дочерний класс часто изменяет не только имена методов базовогокласса, но и аргументы.

конструирование

Page 14: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 14

Варьирование

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

варьирование

Page 15: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 15

Комбинирование

Дочерний класс наследует черты более чем одногородительского класса.

Для комбинирования классов используется механизммножественного наследования.

Page 16: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 16

Правильные формы наследования (is-a)

К правильным формам относятся только те, в которых междудочерним и родительским классом возникает отношение "is-a" или «быть экземпляром», то есть дочерний класс являетсячастным случаем своего предка.

Если B не есть A, то B не стоит наследовать от A.

Пример: Прямоугольник не является частным случаем квадрата,по этому, класс Rectangle не стоит наследовать от классаSquare.

Правильные формы наследования is-a:

⚫Специализация

⚫Спецификация

⚫ Расширение (в большинстве случаев)

⚫Ограничение (иногда)

⚫Комбинирование (иногда)

Page 17: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 17

Правильные формы наследования (тип-подтип)

Для того чтобы класс B был подтипом класса A, он должениметь схожее поведение с классом A во всех существенныхмоментах.

Схожее поведение означает, что класс B должен поддерживатьтот же набор методов, что и класс A.

Пример: Базовый: Геометрическая фигура. Наследники:Окружность, Треугольник, Прямоугольник и т.д.

Правильные формы наследования "тип−подтип“:

⚫ Специализация

⚫ Спецификация

⚫ Обобщение

⚫ Расширение

⚫ Конструирование (очень редко)

⚫ Варьирование (иногда)

⚫ Комбинирование

Page 18: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 18

Формы наследования

Абсолютно правильные формы наследования:

⚫ Специализация

⚫ Спецификация

⚫ Расширение - если производный класс есть частный случайбазового

⚫ Комбинирование- если производный класс есть частный случайбазовых и является подтипом базовых типов

Допустимые формы наследования:

⚫ Обобщение

⚫ Ограничение

⚫ Варьирование

⚫ Комбинирование - если производный класс не является частнымслучаем базовых

Недопустимые формы наследования:

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

Page 19: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 19

Порождающие шаблоны проектирования

Page 20: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 20

Паттерны (шаблоны проектирования)

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

В общем случае паттерн состоит из четырех основных элементов:

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

Задача - это описание того, когда следует применять паттерн. Необходимосформулировать задачу и ее контекст. Может описываться конкретная проблемапроектирования, например способ представления алгоритмов в виде объектов.Так же задача может включать перечень условий, при выполнении которыхимеет смысл применять данный паттерн.

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

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

Page 21: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 21

Классификация паттернов

Паттерны проектирования программных систем делятся наследующие категории:

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

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

Идиомы - низкоуровневые паттерны, имеют дело с вопросамиреализации какой-либо проблемы с учетом особенностейданного языка программирования.

Page 22: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 22

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

Паттерны проектирования делятся на следующие категории:

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

Структурные - шаблоны проектирования, в которыхрассматривается вопрос о том, как из классов и объектовобразуются более крупные структуры.

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

Page 23: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 23

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

● Singleton (Одиночка) - контролирует создание единственногоэкземпляра некоторого класса и предоставляет доступ к нему.

● Factory Method (Фабричный метод) - В его классическом вариантевводится полиморфный класс Factory, в котором определяетсяинтерфейс фабричного метода, а ответственность за созданиеобъектов конкретных классов переносится на производные от Factoryклассы, в которых этот метод переопределяется.

● Abstract Factory (Абстрактная фабрика) - использует несколькофабричных методов и предназначен для создания целого семействаили группы взаимосвязанных объектов.

● Builder (Строитель) - определяет процесс поэтапногоконструирования сложного объекта, в результате которого могутполучаться разные представления этого объекта.

● Prototype (Прототип) - создает новые объекты с помощьюпрототипов. Прототип - некоторый объект, умеющий создавать позапросу копию самого себя.

● Object Pool (Пул объектов) - используется в случае, когда созданиеобъекта требует больших затрат или может быть создано толькоограниченное количество объектов некоторого класса.

Page 24: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 24

Singleton

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

◦ Такая переменная доступна всегда. Время жизни глобальнойпеременной - от запуска программы до ее завершения.

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

Singleton возлагает контроль над созданием единственногообъекта на сам класс.

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

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

Page 25: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 25

Реализация Singletonclass Singleton

{

public:

static Singleton* GetInstance()

{

_instance=new Singleton();

return _instance;

}

void Method1(){cout<<"Method1\n";}

void Method2(){cout<<"Method2\n";}

private:

Singleton(){}

static Singleton* _instance;

};

Singleton::_instance=NULL;

int main()

{

Singleton* singleton = Singleton::GetInstance();

singleton->Method1();

singleton->Method2();

}

Page 26: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 26

Преимущества и недостатки

Преимущества паттерна Singleton

◦ Класс сам контролирует процесс создания единственногоэкземпляра.

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

◦ Возможность создания объектов классов, производных отSingleton.

Недостатки паттерна Singleton

◦ В случае использования нескольких взаимозависимыходиночек их реализация может усложниться.

Page 27: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 27

Factory Method

Паттерн Factory Method может быть полезным в решенииследующих задач:

1. Система должна оставаться расширяемой путем добавленияобъектов новых типов. Непосредственное использованиеоператора new является нежелательным, так как в этомслучае код создания объектов с указанием конкретных типовможет получиться разбросанным по всему приложению. Тогдатакие операции как добавление в систему объектов новыхтипов или замена объектов одного типа на другой будутзатруднительными. Паттерн Factory Method позволяет системеоставаться независимой как от самого процесса порожденияобъектов, так и от их типов.

1. Заранее известно, когда нужно создавать объект, нонеизвестен его тип.

Page 28: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 28

Описание паттерна Factory Method

Для того, чтобы система оставалась независимой от различных типовобъектов, паттерн Factory Method использует механизм полиморфизма -классы всех конечных типов наследуются от одного абстрактногобазового класса, предназначенного для полиморфного использования. Вэтом базовом классе определяется единый интерфейс, через которыйпользователь будет оперировать объектами конечных типов.

Для обеспечения относительно простого добавления в систему новых типовпаттерн Factory Method локализует создание объектов конкретных типов вспециальном классе-фабрике. Методы этого класса, посредством которыхсоздаются объекты конкретных классов, называются фабричными.

Существуют две разновидности паттерна Factory Method:

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

Классический вариант фабричного метода, когда интерфейс фабричныхметодов объявляется в независимом классе-фабрике, а их реализацияопределяется конкретными подклассами этого класса.

Page 29: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 29

Классическая реализация Factory Method. Классы-результаты фабрики

class BaseClass {

public:

virtual string GetName() = 0;

virtual ~BaseClass(){}

};

class DerivedClass1 : public BaseClass {

public:

virtual string GetName() {

return "Derived Class 1\n";

}

};

class DerivedClass2 : public BaseClass {

public:

virtual string GetName() {

return "Derived Class 2\n";

}

};

Page 30: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 30

Классическая реализация Factory Method. Классы фабрик

class Factory {

public:

virtual BaseClass* FactoryMethod() = 0;

};

class Factory1 : public Factory {

public:

virtual BaseClass* FactoryMethod() {

return new DerivedClass1();

}

};

class Factory2 : public Factory {

public:

virtual BaseClass* FactoryMethod() {

return new DerivedClass2();

}

};

Page 31: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 31

Классическая реализация Factory Method. Функция main

int main()

{

const int count = 2;

Factory1 fact1;

Factory2 fact2;

Factory* factories[] = {&fact1, &fact2};

for (int i = 0; i < count; i++)

{

BaseClass* bc = factories[i]->FactoryMethod();

cout << bc->GetName().c_str();

delete bc;

}

} Результат:Derived Class 1

Derived Class 2

Page 32: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 32

Преимущества и недостатки

Преимущества паттерна Factory Method:

◦ Создает объекты разных типов, позволяя системе оставатьсянезависимой как от самого процесса создания, так и оттипов создаваемых объектов.

Недостатки паттерна Factory Method:

◦ В случае классического варианта паттерна даже дляпорождения единственного объекта необходимо создаватьсоответствующую фабрику

Page 33: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 33

Abstract Factory

Паттерн Abstract Factory стоит использовать, когда:

◦ Система должна оставаться независимой как от процессасоздания новых объектов, так и от типов порождаемыхобъектов. Непосредственное использование оператора new вкоде приложения нежелательно.

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

Page 34: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 34

Классы для 1-й фабрики

class BaseClass1 {

public:

virtual string GetName() = 0;

virtual ~BaseClass1(){}

};

class DerivedClass11: public BaseClass1 {

public:

virtual string GetName() {

return "Derived Class 11\n";

}

};

class DerivedClass21 : public BaseClass1 {

public:

virtual string GetName() {

return "Derived Class 21\n";

}

};

Page 35: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 35

Классы для 2-й фабрики

class BaseClass2 {

public:

virtual string GetName() = 0;

virtual ~BaseClass2(){}

};

class DerivedClass12: public BaseClass2 {

public:

virtual string GetName() {

return "Derived Class 12\n";

}

};

class DerivedClass22 : public BaseClass2 {

public:

virtual string GetName() {

return "Derived Class 22\n";

}

};

Page 36: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 36

Классы фабрик

class AbstractFactory {

public:

virtual BaseClass1* FactoryMethod1() = 0;

virtual BaseClass2* FactoryMethod2() = 0;

};

class AbstractFactory1 : public AbstractFactory {

public:

virtual BaseClass1* FactoryMethod1() {

return new DerivedClass11(); }

virtual BaseClass2* FactoryMethod2() {

return new DerivedClass12(); }

};

class AbstractFactory2 : public AbstractFactory {

public:

virtual BaseClass1* FactoryMethod1() {

return new DerivedClass21(); }

virtual BaseClass2* FactoryMethod2() {

return new DerivedClass22(); }

};

Page 37: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 37

Функция main

void UseAbstractFactory(AbstractFactory* af)

{

BaseClass1* bc1=af->FactoryMethod1();

BaseClass2* bc2=af->FactoryMethod2();

cout<<bc1->GetName().c_str();

cout<<bc2->GetName().c_str();

}

int main()

{

AbstractFactory* af1=new AbstractFactory1();

AbstractFactory* af2=new AbstractFactory2();

UseAbstractFactory(af1);

UseAbstractFactory(af2);

}

Результат:Derived Class 11

Derived Class 12

Derived Class 21

Derived Class 22

Page 38: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 38

Builder

Паттерн Builder может помочь в решении следующих задач:

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

◦ Данные должны иметь несколько представлений. Приведемклассический пример. Пусть есть некоторый исходныйдокумент в формате RTF (Rich Text Format), в общем случаесодержащий текст, графические изображения и служебнуюинформацию о форматировании (размер и тип шрифтов,отступы и др.). Если этот документ в формате RTFпреобразовать в другие форматы (например, Microsoft Wordили простой ASCII-текст), то полученные документы и будутпредставлениями исходных данных.

Page 39: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 39

Описание паттерна Builder

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

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

Page 40: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 40

Реализация паттерна Builder. Класс Computer

class Computer {

// Поля сделаны паблик, в виду

// ограниченности места на слайде.

// В реальности, это надо реализовывать

// через методы доступа к приватным полям!

public:

string Name;

string CPU;

string RAM;

string HDD;

string VGA;

void Print() {

cout<<Name.c_str()<<": "

<<CPU.c_str()<<“ / "

<<RAM.c_str()<<“ / "

<<HDD.c_str()<<“ / "

<<VGA.c_str()<<"\n";

}

};

Page 41: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 41

Классы-строителиclass ICompBuilder {

public: virtual Computer Build()=0;

};

class GameCompBuilder: public ICompBuilder {

private: Computer _computer;

public: GameCompBuilder(){};

virtual Computer Build() {

_computer.Name="Game Computer";

_computer.CPU="Core i7 3.0 GHz";

_computer.RAM="8 Gb";

_computer.HDD="1 Tb";

_computer.VGA="GeForce GTX 560";

return _computer;

} };

class OfficeCompBuilder: public ICompBuilder {

private: Computer _computer;

public: OfficeCompBuilder(){};

virtual Computer Build() {

_computer.Name="Office Computer";

_computer.CPU="Core i3 3.0 GHz";

_computer.RAM="2 Gb";

_computer.HDD="500 Gb";

_computer.VGA="Intel GMA 4000";

return _computer;

} };

Page 42: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 42

Класс-директор

class Director {

public:

Director(){_builder=NULL;};

void SetBuilder(ICompBuilder* builder)

{

_builder=builder;

}

Computer GetComp()

{

return _builder->Build();

}

private:

ICompBuilder* _builder;

};

Page 43: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 43

Использование строителей

int main()

{

Director* director=new Director();

//Building Game Computer

director->SetBuilder(new GameCompBuilder);

Computer comp=director->GetComp();

comp.Print();

//Building Office Computer

director->SetBuilder(new OfficeCompBuilder);

comp=director->GetComp();

comp.Print();

}

Результат:Game Computer: Core i7 3.0 GHz / 8 Gb / 1 Tb / GeForce GTX 560

Office Computer: Core i3 3.0 GHz / 2 Gb / 500 Gb / Intel GMA 4000

Page 44: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 44

Преимущества и недостатки

Преимущества паттерна Builder:

◦ Возможность контролировать процесс создания сложногопродукта.

◦ Возможность получения разных представлений некоторыхданных.

Недостатки паттерна Builder:

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

Page 45: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 45

Prototype

Паттерн Prototype (прототип) можно использовать в следующихслучаях:

◦ Система должна оставаться независимой как от процессасоздания новых объектов, так и от типов порождаемыхобъектов. Непосредственное использование оператора new вкоде приложения считается нежелательным.

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

Page 46: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 46

Реализация Prototype

class IProduct {

public:

virtual IProduct* Clone()=0;

virtual void Print()=0;

};

class Product1: public IProduct {

private:

string _strSomeField1;

public:

Product1(string strField) {

_strSomeField1=strField;

}

virtual IProduct* Clone() {

return new Product1(*this);

}

virtual void Print() {

cout<<"Address: "<<this<<"\n";

cout<<"Field: "<<_strSomeField1.c_str()<<"\n";

}

};

Page 47: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 47

Реализация Prototype

class Product2: public IProduct {

private:

string _strSomeField2;

public:

Product2()

{

_strSomeField2="";

}

virtual void Print() {

cout<<"Address: "<<this<<"\n";

cout<<"Field: "<<_strSomeField2.c_str()<<"\n";

}

};

Page 48: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 48

Использование Prototype

int main()

{

IProduct* prod1=new Product1("Product 1");

IProduct* prod2=prod1->Clone();

Product1* prod3=(Product1*)prod1->Clone();

Product2* prod4=(Product2*)prod1->Clone();

prod1->Print();

prod2->Print();

prod3->Print();

prod4->Print();

}

Результат:Address: 004492E8

Field: Product 1

Address: 00449348

Field: Product 1

Address: 004493A8

Field: Product 1

Address: 00449408

Field: Product 1

Page 49: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 49

Преимущества и недостатки

Преимущества паттерна Prototype

◦ Для создания новых объектов клиенту необязательно знатьих конкретные классы.

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

Недостатки паттерна Prototype

◦ Каждый тип создаваемого продукта должен реализовыватьоперацию клонирования clone(). В случае, если требуетсяглубокое копирование объекта (объект содержит ссылки илиуказатели на другие объекты), это может быть непростойзадачей.

Page 50: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 50

Object Pool

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

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

Page 51: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 51

Реализация Object Pool на основе Singleton. Классы объектов

class IObject {

protected:

string _strText;

public:

virtual void Print() {

cout<<"The Object is: "<<_strText.c_str()<<"\n";

} };

class Object1: public IObject {

public:

Object1(){

_strText="Object 1";

} };

class Object2: public IObject {

public:

Object2(){

_strText="Object 2";

} };

class Object3: public IObject {

public:

Object3(){

_strText="Object 3";

} };

class Object4: public IObject {

public:

Object4(){

_strText="Object 4";

} };

Page 52: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 52

Object Pool

template<unsigned poolSize> class ObjectPool{

public:

static ObjectPool* GetInstance() {

if (!_instance) _instance=new ObjectPool();

return _instance;

}

IObject* GetObject() {

for (unsigned i=0;i<poolSize;i++)

{ if (!_busyObjects[i]){

_busyObjects[i]=true;

return _objectPool[i];

} }

return NULL;

}

void ReleaseObject(IObject* object){

for (unsigned i=0;i<poolSize;i++)

{ if (_objectPool[i]==object){

_busyObjects[i]=false;

} }

}

...

Page 53: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 53

Object Pool...

private:

ObjectPool(){

for (unsigned i=0;i<poolSize;i++)

{

unsigned iObjNumber=rand()%4;

switch (iObjNumber)

{

case 0: _objectPool[i]=new Object1(); break;

case 1: _objectPool[i]=new Object2(); break;

case 2: _objectPool[i]=new Object3(); break;

case 3: _objectPool[i]=new Object4(); break;

}

_busyObjects[i]=false;

}

}

private:

IObject* _objectPool[poolSize];

bool _busyObjects[poolSize];

static ObjectPool* _instance;

};

Page 54: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 54

Использование Object Pooltemplate<unsigned poolSize>

ObjectPool<poolSize>* ObjectPool<poolSize>::_instance=NULL;

int main()

{

ObjectPool<5>* op=ObjectPool<5>::GetInstance();

IObject* object1=op->GetObject();

if (object1) object1->Print(); else cout<<"The Object is: NULL\n";

IObject* object2=op->GetObject();

if (object2) object2->Print(); else cout<<"The Object is: NULL\n";

IObject* object3=op->GetObject();

if (object3) object3->Print(); else cout<<"The Object is: NULL\n";

IObject* object4=op->GetObject();

if (object4) object4->Print(); else cout<<"The Object is: NULL\n";

IObject* object5=op->GetObject();

if (object5) object5->Print(); else cout<<"The Object is: NULL\n";

IObject* object6=op->GetObject();

if (object6) object6->Print(); else cout<<"The Object is: NULL\n";

IObject* object7=op->GetObject();

if (object7) object7->Print(); else cout<<"The Object is: NULL\n";

op->ReleaseObject(object2);

IObject* object8=op->GetObject();

if (object8) object8->Print(); else cout<<"The Object is: NULL\n";

}

Page 55: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 55

Результат

The Object is: Object 2

The Object is: Object 4

The Object is: Object 3

The Object is: Object 1

The Object is: Object 2

The Object is: NULL

The Object is: NULL

The Object is: Object 4

Page 56: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 56

Преимущества и недостатки

◦ Пул объектов отслеживает объекты, которые он создает.

◦ Паттерн Object Pool может использоваться для инкапсуляциилогики создания объектов. Однако он не управляет имипосле их создания.

◦ Достоинством этого паттерна является быстрое созданиеобъектов, однако это реализовано за счет использованиябольших ресурсов памяти.

Page 57: C++ Базовый. Занятие 16.

http://www.slideshare.net/IgorShkulipa 57

Лабораторная работа №16. Порождающие шаблоны

1. Создать класс «Игральная карта» и наследников от него.Создать класс «Колода карт», обрабатывающий выдачу картигроку на основе паттерна Object Pool.

1. Создать классы «Односвязный список», «Двусвязный список»,«Циклический список», на основе общего интерфейса.Реализовать методы доступа к элементам, сортировки инахождения максимума/минимума. Реализовать созданиеконкретных списков на основе фабричного метода.