Абстрактная фабрика с абстрактными параметрами? - PullRequest
8 голосов
/ 05 июня 2011

Я пытаюсь разработать хорошую систему создания сущностей с абстрактной фабрикой (согласно http://www.dofactory.com/Patterns/PatternAbstract.aspx), но я испытываю затруднения, когда дело доходит до конкретных параметров экземпляра.

Например: Iиметь две абстрактные фабрики, одну для создания снаряда и одну для создания ящика

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

Но я борюсь с тем, чтобы в конце концов у меня был этот абстрактный метод фабрикикоторый я вызываю с такими параметрами, как строка «BulletProjectile» и «WeakCrate», мне нужно предоставить конкретные параметры экземпляра, и что более важно, они имеют разные типы для разных фабрик - для снарядов они будут иметь положение и скорость, а ящик будет простоиметь положение. Худший сценарий, когда пользователь или игрокон может найти ящик или подобный предмет и может определить его размеры.Как бы я справился с этим?

1 Ответ

5 голосов
/ 05 июня 2011

Пара вариантов:

Переосмыслите свое использование

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

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

Вот несколько вариантов для размышления:

  • Укажите несколько абстрактных типов фабрики, с одним методом Create, таким как GrenadeFactory и BulletFactory
  • Предоставление нескольких методов для одного абстрактного типа фабрики, таких как CreateBullet и CreateGrenade
  • Хватит использовать абстрактные фабрики. Это хороший вариант, если вам действительно не нужна абстрактная конструкция , и вам просто нужны абстрактные типы.

Помните, что вы все равно можете передать производный тип (Bullet) в метод, принимающий базовый тип (скажем, Entity или Projectile).

Двойная отправка

Если вы действительно настроены на объединение абстрактных фабрик с абстрактными параметрами, то вам может потребоваться двойная диспетчеризация или Шаблон посетителя . Ключевым моментом здесь является то, что вы пытаетесь объединить два разных виртуальных метода и получить уникальную комбинацию поведения на основе этих двух производных типов.

Это потребует от вас создания базовых и производных типов для ваших параметров, чтобы вы не могли передавать простые типы (например, int, string и т. Д.) Без создания пользовательской структуры параметров, производной от базового Parameters типа.

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

RTTI

Вы можете использовать функцию информации о типах C ++ .

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

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

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

Имущественная сумка

Вы также можете использовать словарь string -> some type (например, string -> boost::any). Это называется сумкой свойств. Тем не менее, он теряет большую безопасность типов времени компиляции, потому что вы в основном просматриваете все по строковому значению. Я не очень рекомендую это.

...