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

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

Upload: igor-shkulipa

Post on 21-Mar-2017

60 views

Category:

Education


0 download

TRANSCRIPT

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

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

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

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

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

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

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

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

Ассоциация

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

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

Агрегация

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

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

Композиция

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

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

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

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

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

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

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

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

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

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

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

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

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

3. Обобщение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Обобщение

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

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

обобщение

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

Расширение

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

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

расширение

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

Ограничение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

⚫ Обобщение

⚫ Расширение

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

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

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

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

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

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

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

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

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

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

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

⚫ Обобщение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Singleton

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

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

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

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

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

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

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

}

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

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

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

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

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

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

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

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

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

Factory Method

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

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

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

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

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

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

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

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

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

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

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";

}

};

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

}

};

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

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

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

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

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

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

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

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

Abstract Factory

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

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

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

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";

}

};

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";

}

};

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

};

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

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

Builder

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

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

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

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

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

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

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

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";

}

};

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;

} };

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;

};

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

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

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

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

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

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

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

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

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

Prototype

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

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

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

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";

}

};

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";

}

};

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

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

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

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

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

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

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

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

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

Object Pool

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

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

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";

} };

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;

} }

}

...

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;

};

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";

}

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

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

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

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

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

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

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

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

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

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