我正在尝试使用抽象工厂设计一个好的实体创建系统(根据http://www.dofactory.com/Patterns/PatternAbstract.aspx)但是当涉及到实例特定参数时,我正在努力。
例如: 我有两个抽象工厂,一个用于创建一个抛射物,另一个用于创建一个箱子
现在工厂可以是每个类型的一个实例,它从列表中传递一个抽象参数集(在基类中将共享材料,大小等),类型特定参数将是弹丸的速度和箱子的耐久性。
但是我正在努力的是,最后当我有这个抽象的工厂方法,我用字符串“BulletProjectile”和“WeakCrate”这样的参数调用时,我需要提供特定于实例的参数,更重要的是对于不同的工厂,它们具有不同的类型 - 对于射弹而言,它们具有位置和速度,并且箱子将具有位置。 更糟糕的情况是用户或玩家正在创建板条箱或类似对象,并且能够定义其尺寸。我该如何处理?
答案 0 :(得分:5)
几个选项:
重新考虑您的使用
如果将工厂用户与确切类型的生成方式分开,则抽象工厂非常有用。抽象工厂对它产生的东西没有任何限制,只是它是抽象的。它可以返回非抽象类型,或者不在继承层次结构基础上的抽象类型。
如果使用工厂的代码已经可以获得不同的数据集来调用工厂,那么使用工厂的代码已经知道了它的类型。
以下是一些需要考虑的选项:
Create
方法,例如GrenadeFactory
和BulletFactory
CreateBullet
和CreateGrenade
请记住,您仍然可以将派生类型(Bullet
)传递给采用基本类型的方法(例如,Entity
或Projectile
)。
双重发送
如果您真的已经将抽象工厂与抽象参数组合在一起,那么您可能希望研究双重调度或Visitor Pattern。关键在于您尝试将两种不同的虚拟方法相互组合,并根据这两种派生类型获得独特的行为组合。
这将要求您为参数创建基类型和派生类型,因此无法创建从基类Parameters
类型派生的自定义参数结构,因此无法传递简单类型(如int,string等)
还需要大量额外代码来实现访问者模式。
<强> RTTI 强>
您可以使用the C++ Run-Time Type Information feature。
使用dynamic_cast
,可以将基类型转换为派生类型。您可以在工厂实现中执行此操作,以将基本参数类型转换为特定参数类型。
与double-dispatch一样,这也需要您为参数创建一个类型层次结构,但需要较少的代码将它们拼接在一起(不需要访问者模式)。
但是,此选项会将工厂实现与参数结构实现紧密结合。
物业袋
您还可以使用string
- &gt; some type
字典(string
- &gt; boost::any
,例如)。这被称为财产袋。但是,它失去了很多编译时类型的安全性,因为你基本上是按字符串值查找所有内容。我真的不推荐它。