Студопедия
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

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

Читайте также:
  1. Введение в паттерны проектирования
  2. Введение в паттерны проектирования
  3. Введение в паттерны проектирования
  4. Введение в паттерны проектирования
  5. Введение в паттерны проектирования
  6. Введение в паттерны проектирования
  7. Гдд Паттерны поведения
  8. Глава 1. Введение в паттерны проектирования
  9. Глава 3. Порождающие паттерны
  10. Глава 4. Структурные паттерны

 

protected:

virtual Product* CreateProduct(); private:

Product* _product;

Product* Creator::GetProduct () { if (.product == 0) {

_product = CreateProduct ();

return _product;

а использование шаблонов, чтобы не порождать подклассы. К сожалению, до­пустима ситуация, когда вам придется порождать подклассы только для того, чтобы создать подходящие объекты-продукты. В C++ этого можно из­бежать, предоставив шаблонный подкласс класса Creator, параметризо­ванный классом Product:

class Creator { public:

virtual Product* CreateProduct () = 0; I.

template <class TheProduct>

class StandardCreator: public Creator {

public:

virtual Product* CreateProduct();

template <class TheProduct>

Product* StandardCreator<TheProduct>::CreateProduct () {

return new TheProduct; }

С помощью данного шаблона клиент передает только класс продукта, по­рождать подклассы от Creator не требуется:

class MyProduct: public Product { public:

MyProduct();

StandardCreator<MyProduct> myCreator;

а соглашения об именовании. На практике рекомендуется применять такие согла­шения об именах, которые дают ясно понять, что вы пользуетесь фабричными методами. Например, каркас МасАрр на платформе Macintosh [App89] всегда объявляет абстрактную операцию, которая определяет фабричный метод, в ви­де Class* DoMakeClass (), где Class - это класс продукта.


 

Паттерн Factory Method

Пример кода

Функция CreateMaze строит и возвращает лабиринт. Одна из связанных с ней проблем состоит в том, что классы лабиринта, комнат, дверей и стен жестко «зашиты» в данной функции. Мы введем фабричные методы, которые позволят выбирать эти компоненты подклассам.

Сначала определим фабричные методы в игре MazeGame для создания объек­тов лабиринта, комнат, дверей и стен:

class MazeGame { public:

Maze* CreateMaze();

// фабричные методы:

virtual Maze* MakeMazeO const

{ return new Maze; } virtual Room* MakeRoom(int n) const

{ return new Room(n); } virtual Wall* MakeWalK) const

{ return new Wall; } virtual Door* MakeDoor(Room* rl, Room* r2) const

{ return new Door(rl, r2); }

Каждый фабричный метод возвращает один из компонентов лабиринта. Класс MazeGame предоставляет реализации по умолчанию, которые возвращают прос­тейшие варианты лабиринта, комнаты, двери и стены.

Теперь мы можем переписать функцию CreateMaze с использованием этих фабричных методов:

Maze* MazeGame::CreateMaze () { Maze* aMaze = MakeMaze();

Room* rl = MakeRoom(l); Room* r2 = MakeRoom(2); Door* theDoor = MakeDoor(rl, r2);

aMaze->AddRoom(rl); aMaze->AddRoom(r2);

rl->SetSide (North, MakeWall()); rl->SetSide(East, theDoor); rl->SetSide (South, MakeWall()); rl->SetSide(West, MakeWall());

r2->SetSide (North, MakeWall()); r2->SetSide(East, MakeWall()); r2->SetSide (South, MakeWall()); r2->SetSide(West, theDoor);


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

return aMaze;

В играх могут порождаться различные подклассы MazeGame для специализа­ции частей лабиринта. В этих подклассах допустимо переопределение некоторых или всех методов, от которых зависят разновидности продуктов. Например, в игре BombedMazeGame продукты Room и Wall могут быть переопределены так, чтобы возвращать комнату и стену с заложенной бомбой:

class BombedMazeGame: public MazeGame { public:

BombedMazeGame();

virtual Wall* MakeWall() const { return new BombedWall; }

virtual Room* MakeRoom(int n) const { return new RoomWithABomb(n); }

А в игре Enchant edMazeGame допустимо определить такие варианты:

class EnchantedMazeGame: public MazeGame { public:

EnchantedMazeGame();

virtual Room* MakeRoomdnt n) const

{ return new EnchantedRoom(n, CastSpell()); }

virtual Door* MakeDoor(Room* rl, Room* r2) const

{ return new DoorNeedingSpell(rl, r2); } protected:

Spell* CastSpell() const;

Известные применения

Фабричные методы в изобилии встречаются в инструментальных библиоте­ках и каркасах. Рассмотренный выше пример с документами - это типичное при­менение в каркасе МасАрр и библиотеке ЕТ++ [WGM88]. Пример с манипулято­ром заимствован из каркаса Unidraw.

Класс View в схеме модель/вид/контроллер из языка Smalltalk-80 имеет ме­тод defaultController, который создает контроллер, и этот метод выглядит как фабричный [РагЭО]. Но подклассы View специфицируют класс своего кон­троллера по умолчанию, определяя метод def aultControllerClass, возвраща­ющий класс, экземпляры которого создает defaultController. Таким образом, реальным фабричным методом является def aultControllerClass, то есть метод, который должен переопределяться в подклассах.

Более необычным является пример фабричного метода parserClass, тоже взятый из Smalltalk-80, который определяется поведением Behavior (суперкласс




Дата добавления: 2015-09-11; просмотров: 84 | Поможем написать вашу работу | Нарушение авторских прав

Глава 3. Порождающие паттерны | Порождающие паттерны | Паттерн Abstract Factory | Результаты | Порождающие паттерны | Паттерн Builder | Пример кода | Паттерн Builder | Назначение | Порождающие паттерны |


lektsii.net - Лекции.Нет - 2014-2025 год. (0.005 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав