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

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

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

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

class EnchantedMazeFactory: public MazeFactory { public:

EnchantedMazeFactory();

virtual Room* MakeRoom(int n) const

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

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

protected:

Spell* CastSpell() const;

А теперь предположим, что мы хотим построить для некоторой игры лаби­ринт, в одной из комнат которого заложена бомба. Если бомба взрывается, то она как минимум обрушивает стены. Тогда можно породить от класса Room под­класс, отслеживающий, есть ли в комнате бомба и взорвалась ли она. Также нам понадобится подкласс класса Wall, который хранит информацию о том, был ли нанесен ущерб стенам. Назовем эти классы соответственно RoomWithABomb и BombedWall.

И наконец, мы определим класс BombedMazeFactory, являющийся под­классом BombedMazeFactory, который создает стены класса BombedWall и комнаты класса RoomWithABomb. В этом классе надо переопределить всего две функции:

Wall* BombedMazeFactory::MakeWall () const { return new BombedWall;

Room* BombedMazeFactory::MakeRoom(int n) const { return new RoomWithABomb(n);

}

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

MazeGame game; BombedMazeFactory factory/-

game. CreateMaze (factory);

Для построения волшебных лабиринтов CreateMaze может принимать в ка­честве параметра и EnchantedMazeFactory.

Отметим, что MazeFactory - всего лишь набор фабричных методов. Это са­мый распространенный способ реализации паттерна абстрактная фабрика. Еще заметим, что MazeFactory - не абстрактный класс, то есть он работает и как AbstractFactory, и как ConcreteFactory. Это еще одна типичная


 

Паттерн Abstract Factory

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

В функции CreateMaze используется операция SetSide для описания сто­рон комнат. Если она создает комнаты с помощью фабрики BombedMazeFactory, то лабиринт будет составлен из объектов класса RoomWithABomb, стороны кото­рых описываются объектами класса BombedWall. Если классу RoomWithABomb потребуется доступ к членам BombedWall, не имеющим аналога в его предках, то придется привести ссылку на объекты-стены от типа Wall* к типу BombedWall*. Такое приведение к типу подкласса безопасно при условии, что аргумент действи­тельно принадлежит классу BombedWall*, а это обязательно так, если стены соз­даются исключительно фабрикой BombedMazeFactory.

В динамически типизированных языках вроде Smalltalk приведение, разуме­ется, не нужно, но будет выдано сообщение об ошибке во время выполнения, если объект/класса Wai 1 встретится вместо ожидаемого объекта подкласса класса Wai 1. Использование абстрактной фабрики для создания стен предотвращает такие ошибки, гарантируя, что могут быть созданы лишь стены определенных типов.

Рассмотрим версию MazeFactory на языке Smalltalk, в которой есть единствен­ная операция make, принимающая вид изготавливаемого объекта в качестве парамет­ра. Конкретная фабрика при этом будет хранить классы изготавливаемых объектов.

Для начала напишем на Smalltalk эквивалент CreateMaze:

createMaze: aFactory

rooml room2 aDoor

rooml:= (aFactory make: #room) number: 1. room2:= (aFactory make: #room) number: 2. aDoor:= (aFactory make: #door) from: rooml to: room2. rooml atSide: #north put: (aFactory make: #wall). rooml atSide: #east put: aDoor.

rooml atSide: #south put: (aFactory make: #wall). rooml atSide: #west put: (aFactory make: #wall). room2 atSide: #north put: (aFactory make: #wall). room2 atSide: #east put: (aFactory make: #wall). room2 atSide: #south put: (aFactory make: #wall). room2 atSide: #west put: aDoor. Л Maze new addRoom: rooml; addRoom: room2; yourself

В разделе «Реализация» мы уже говорили о том, что классу MazeFactory

нужна всего одна переменная экземпляра partCatalog, предоставляющая сло­варь, в котором ключом служит класс компонента. Напомним еще раз реализа­цию метода make:

make: partName

Л (partCatalog at: partName) new

Теперь мы можем создать фабрику MazeFactory и воспользоваться ей для реализации createMaze. Данную фабрику мы создадим с помощью метода createMazeFactory класса MazeGame:


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

createMazeFactory

А (MazeFactory new

addPart: Wall named: #wall; addPart: Room named: #room; addPart: Door named: #door; yourself)

BombedMazeFactory и EnchantedMazeFactory создаются путем ассоции­рования других классов с ключами. Например, EnchantedMazeFactory можно создать следующим образом:

createMazeFactory

А (MazeFactory new

addPart: Wall named: #wall; addPart: EnchantedRoom named: #room; addPart: DoorNeedingSpell named: #door; yourself)

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

В библиотеке Interviews [Lin92] для обозначения классов абстрактных фаб­рик используется суффикс «Kit». Так, для изготовления объектов пользователь­ского интерфейса с заданным внешним обликом определены абстрактные фабри­ки WidgetKit и DialogKit. В Interviews есть также класс Lay out Kit, который генерирует разные объекты композиции в зависимости от того, какая требуется стратегия размещения. Например, размещение, которое концептуально можно было бы назвать «в строку», может потребовать разных объектов в зависимости от ориентации документа (книжной или альбомной).

В библиотеке ЕТ++ [WGM88] паттерн абстрактная фабрика применяется для достижения переносимости между разными оконными системами (например, X Windows и SunView). Абстрактный базовый класс Window System определяет ин­терфейс для создания объектов, которое представляют ресурсы оконной системы (MakeWindow, MakeFont, MakeColor и т.п.). Его конкретные подклассы реализу­ют эти интерфейсы для той или иной оконной системы. Во время выполнения ЕТ++ создает экземпляр конкретного подкласса WindowSystem, который уже и порождает объекты, соответствующие ресурсам данной оконной системы.

Родственные паттерны

Классы Abstract Factory часто реализуются фабричными методами (см. паттерн фабричный метод), но могут быть реализованы и с помощью паттерна прототип.

Конкретная фабрика часто описывается паттерном одиночка.




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

Проектирование редактора документов | Подклассы Windowlmp | Операции пользователя | Операции пользователя | Правописание и расстановка переносов | Паттерн итератор | Проектирование редактора документов | Глава 3. Порождающие паттерны | Порождающие паттерны | Паттерн Abstract Factory |


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