class Car

{

public:

virtual Car* clone() const = 0;

virtual const char* getName() const = 0;

virtual void setEngine(Engine* engine);

virtual Engine* getEngine() const;

virtual void setWheels(Wheel* FR, Wheel* FL, Wheel* BR, Wheel* BL);

virtual void setFrontWheels(Wheel* FR, Wheel* FL);

virtual void setBackWheels(Wheel* BR, Wheel* BL);

...

};

Теперь в потомках класса Car нужно перезагрузить и реализовать этот метод, он должен создавать абсолютно идентичную новую копию объекта (см. листинг 6).

Листинг 6

class CarBMW5: public Car

{

public:

virtual Car* clone() const

{

CarBMW5* car = new CarBMW5();

car->setEngine(getEngine()->clone());

car->setFrontWheels(getWheelFR()->clone(), getWheelFL()->clone());

car->setBackWheels(getWheelBR()->clone(), getWheelBL()->clone());

...

return car;

}

...

};

Обратите внимание, что функция клонирования CarBMW5::clone() вызывает функции клонирования для всех своих составных частей. Это стандартная практика: если использовать функцию клонирования в составном объекте, то нужно добавить ее во все объекты, которые он содержит. Таким образом, автомобиль легко клонирует себя, так как просто последовательно запускает процесс копирования всех составных частей и собирает из них новый автомобиль – свою полную копию.

Применений у этого паттерна может быть несколько, как уже было сказано выше. В случае с копированием объектов (Ctrl-C, Ctrl-V) мы будем иметь массив выделенных объектов и при нажатии на Ctrl-C просто создадим их копии, используя метод clone. А нажав на Ctrl-V, мы вставляем эти объекты в нужное место. Мы также можем заранее создать все возможные объекты (типы автомобилей) и поместить их в один массив. А потом легко создавать автомобили по имени: находим объект с нужным именем в массиве и вызываем его метод clone(). Простой пример.

class CarFactory

{

std::vector<Car*> mCarTemplates;

public:

CarCreator()

{

mCarTemplates.push_back(new CarBMW5());

mCarTemplates.push_back(new CarToyotaHiace());

mCarTemplates.push_back(new CarLadaKalina());

}

Car* create(const char* name)

{

for(size_t i = 0; i < mCarTemplates.size(); ++i)

if (strcmp(mCarTemplates[i]->getName(), name) == 0)

return mCarTemplates[i]->clone();

return NULL;

}

};

«Одиночка»

Паттерн Singleton гарантирует, что объект какого-то класса будет создан только один раз. Это, пожалуй, самый спорный из всех шаблонов проектирования. Многие профессионалы объектно- ориентированного проектирования не рекомендуют применять этот паттерн, поскольку считают его обычным аналогом глобальных переменных. Самая простая реализация паттерна Singleton – это так называемый «синглтон Мейерса», где «Одиночка» представляет собой статический локальный объект (это решение небезопасно при работе с нитями).

template<typename T> class Singleton

{

public:

static T& instance()

{

// у класса T есть конструктор по умолчанию

static T theSingleInstance;

return theSingleInstance;

}

};

Чтобы класс стал «Одиночкой», его достаточно породить от Singleton.

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

class CarFactory: public Singleton<CarFactory>

{

... дальше то же, что и в CarFactory из паттерна «Прототип»

};

Все обращения к такому объекту ведутся через метод Instance(). Для создания автомобилей по названию нужно просто написать следующий код.

Car* bmw = CarFactory::instance(). create(«BMW5»);

Car* hiace = CarFactory::instance(). create(«ToyotaHiace»);

При этом объект типа CarFactory фактически будет создан в момент первого вызова метода instance(), а удален только при выходе из программы.

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

Продолжение следует.

Обезопасим себя откражи личной информации

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату