8.2. Использование функции для создания объектов (шаблон фабрики)
8.2. Использование функции для создания объектов (шаблон фабрики)
Проблема
Вместо создания объекта в куче с помощью new вам требуется функция (член или самостоятельная), выполняющая создание объекта, тип которого определяется динамически. Такое поведение достигается с помощью шаблона проектирования Abstract Factory (абстрактная фабрика).
Решение
Здесь есть две возможности. Вы можете:
• создать функцию, которая создает экземпляр объекта в куче и возвращает указатель на этот объект (или обновляет переданный в нее указатель, записывая в него адрес нового объекта);
• создать функцию, которая создает и возвращает временный объект.
Пример 8.2 показывает оба этих способа. Класс Session в этом примере может быть любым классом, объекты которого должны не создаваться непосредственно в коде (т.е. с помощью new), а их создание должно управляться каким-либо другим классом. В этом примере управляющий класс — это SessionFactory.
Пример 8.2. Функции, создающие объекты
#include <iostream>
class Session {};
class SessionFactory {
public:
Session Create();
Session* CreatePtr();
void Create(Session*& p);
// ...
};
// Возвращаем копию объекта в стеке
Session SessionFactory::Create() {
Session s;
return(s);
}
// Возвращаем указатель на объект в куче
Session* SessionFactory::CreatePtr() {
return(new Session());
}
// Обновляем переданный указатель, записывая адрес
// нового объекта
void SessionFactory::Create(Session*& p) {
p = new Session();
}
static SessionFactory f; // Единственный объект фабрики
int main() {
Session* p1;
Session* p2 = new Session();
*p2 = f.Create(); // Просто присваиваем объект, полученный из Create
p1 = f.CreatePtr(); // или полученный указатель на объект в куче
f.Create(p1); // или обновляем указатель новым адресом
}
Обсуждение
Пример 8.2 показывает несколько различных способов написания функции, возвращающей объект. Сделать так вместо обращения к new может потребоваться, если создаваемый объект берется из пула, связан с оборудованием или удаление объектов должно управляться не вызывающим кодом. Существует множество причин использовать этот подход (и именно поэтому существует шаблон проектирования для него), я привел только некоторые. К счастью, реализация шаблона фабрики в C++ очень проста.
Наиболее часто используют возврат адреса нового объекта в куче или обновление адреса указателя, переданного как аргумент. Их реализация показана в примере 8.2, и она тривиальна и не требует дальнейших пояснений. Однако возврат из функции целого объекта используется реже — возможно, потому, что это требует больших накладных расходов.
При возврате временного объекта в стеке тела функции создается временный объект. При выходе из функции компилятор копирует данные из временного объекта в другой временный объект, который и возвращается из функции, Наконец, в вызывающей функции объекту с помощью оператора присвоения присваивается значение временного объекта. Это означает, что на самом деле создается два объекта: объект в функции фабрики и временный объект, который возвращается из функции, содержимое которого затем копируется в целевой объект. Здесь осуществляется большое количество копирований (хотя компилятор может оптимизировать временный объект), так что при работе с большими объектами или частыми вызовами этой функции фабрики внимательно следите за тем, что в ней происходит.
Также эта методика копирования временных объектов работает только для объектов, которые ведут себя как объекты значений, что означает, что когда он копируется, то новая версия будет эквивалентна оригинальной. Для большинства объектов это выполняется, но для некоторых — нет. Например, рассмотрим создание объекта класса, прослушивающего сетевой порт. При создании экземпляра объекта он может начинать прослушивать целевой порт, так что скопировать его в новый объект не получится, так как при этом появятся два объекта, пытающиеся слушать один и тот же порт. В этом случае следует возвращать адрес объекта в куче.
Если вы пишете функцию или метод, создающий объекты, то посмотрите также рецепт 8.12. Используя шаблоны, функций можно написать одну функцию, которая будет возвращать новый объект любого типа. Например:
template<typename T>
T* createObject() {
return(new T());
}
MyClass* p1 = createObject();
MyOtherClass* p2 = createObject();
// ...
Этот подход удобен, если требуется единственная функция фабрики, которая сможет одинаковым образом создавать объекты любых классов (или группы связанных классов), что позволит избежать избыточного многократного кодирования функции фабрики.
Смотри также
Рецепт 8.12.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Использование box-shadow для создания состояния focus
Использование box-shadow для создания состояния focus Мы можем пойти дальше в улучшении взаимодействия с этой формой, используя свойство box-shadow на тех элементах, которые находятся в состоянии :focus. Это быстро, легкои, как и прежний CSS3-код, не затрагивает старые
Использование Internet Explorer для создания диалоговых окон
Использование Internet Explorer для создания диалоговых окон Процесс создания сценария WSH, использующего Internet Explorer в качестве интерфейса, можно условно разделить на несколько этапов:? создание HTML-формы в отдельном файле;? написание функции для сценария WSH, в которой будет
Команды создания геометрических объектов
Команды создания геометрических объектов Все команды, предназначенные для создания различных геометрических объектов на чертеже, объединены на панели инструментов Геометрия (рис. 2.3). По умолчанию эта панель размещается первой на компактной панели. Рис. 2.3. Панель
Использование инструментов Visual Studio для создания базы данных
Использование инструментов Visual Studio для создания базы данных Существует несколько способов создания баз данных в SQL Server. С помощью набора инструментов SQL Enterprise Manager базы данных можно создавать графически или программно (с помощью команд на языке SQL). Помимо него, существует
Использование конструктора представлений для создания объединений
Использование конструктора представлений для создания объединений Поскольку создание объединений может составлять самую сложную часть запросов, особенно когда задействовано более двух таблиц, неплохо было бы при создании таких запросов иметь некоторое подспорье. К
2.3. Использование Crystal Reports для создания отчетов
2.3. Использование Crystal Reports для создания отчетов 2.3.1. Подготовка данных для отчета Crystal Reports (фирма Crystal Decisions, www.crystaldecisions.com) является признанным лидером среди недорогих генераторов отчетов, работающих на платформе Windows. Простота использования и широкие функциональные
Шаблоны и функции фабрики в контексте пространства имен
Шаблоны и функции фабрики в контексте пространства имен (Врезка)В основной статье, я утверждаю, что статические методы классов должны быть реализованы как внешние функции всякий раз, когда это возможно, потому что это увеличивает инкапсуляцию класса. Здесь я
7.1. Использование детали-заготовки для имитации создания сборки
7.1. Использование детали-заготовки для имитации создания сборки Рассмотрим пример моделирования крепления оптической детали в оправе резьбовым кольцом по исходным данным рис. 6.10. На первом этапе необходимо построить модели трех деталей.При создании моделей следует
У9.1 Модели создания объектов
У9.1 Модели создания объектов При обсуждении автоматического управления памятью рассмотрен подход, основанный на создании внутренних списков свободной памяти. В этом случае память, занимаемая утилизированными объектами, не возвращается операционной системе, а остается
Использование родительской процедуры создания
Использование родительской процедуры создания Еще один пример иллюстрирует типичный случай переименования процедуры создания класса. Вспомните класс ARRAYED_STACK, полученный порождением от STACK и ARRAY. Процедура создания ARRAY размещает в памяти массив с заданными границами:make
Глава 14 Использование слоев для создания анимации
Глава 14 Использование слоев для создания анимации Здесь мы продолжим начатый в главе 5 разговор о слоях и их использовании. А поскольку данная часть полностью посвящена анимации, то и разговор пойдет о создании анимированных изображений с помощью слоев.Как мы помним из