1

我有一个Person看起来像这样的类:

class Person(object):
    def __init__(self, health, damage):
        self.health = health
        self.damage = damage

    def attack(self, victim):
        victim.hurt(self.damage)

    def hurt(self, damage):
        self.health -= damage

我还有一个Event类,它包含在事件触发时调用的侦听器函数。让我们为实例添加一些事件:

    def __init__(self, health, damage):
        self.health = health
        self.damage = damage
        self.event_attack = Event() # fire when person attacks
        self.event_hurt = Event() # fire when person takes damage
        self.event_kill = Event() # fire when person kills someone
        self.event_death = Event() # fire when person dies

现在,我希望我的事件将某些数据发送到带有**kwargs. 问题是,我希望所有四个事件都发送attackervictim。这使它有些复杂,我必须将其attacker作为参数提供给hurt()-method,然后再次引发attackerinvictimhurt()-method 事件:

def attack(self, victim):
    self.event_attack.fire(victim=victim, attacker=self)
    victim.hurt(self, self.damage)

def hurt(self, attacker, damage):
    self.health -= damage
    self.event_hurt.fire(attacker=attacker, victim=self)
    if self.health <= 0:
        attacker.event_kill.fire(attacker=attacker, victim=self)
        self.event_death.fire(attacker=attacker, victim=self)

我认为我什至不应该attacker作为hurt()-method 的参数,因为它不需要伤害,只需要引发事件。此外,event_kill在受害者的- 方法中引发攻击者的 - 事件hurt()几乎不反对封装。

我应该如何设计这些事件,以便它们遵循封装并且通常更有意义?

4

1 回答 1

1

你根据一个非常具体的情况要求一个非常笼统的答案。我想给出一个更模糊的答案,它忘记了你目前的具体情况。所以也许这太笼统了,无法直接应用于您的情况。

Tubmud,我们设计了一个事件系统,我们不止一次地重新设计它来满足我们的所有需求,但它仍然无法处理我们能想到的所有事情。但是您的示例非常有名,并且会在那里找到适当的表示。

该系统基于一个全局事件服务器(单例,GES),所有事件侦听器都将注册到该服务器,所有事件分发都将由 GES 处理。不涉及直接调用其他对象。

如果一个人对另一个人进行攻击,它会简单地告诉 GES 发送了一个攻击事件。然后,GES 将(基于事件发生的位置,但超出范围)将该事件发送给所有涉及的攻击侦听器(监护人角度、受害者、攻击者、武器……)。

现在受害者也将收到该事件(将由 GES 调用),然后作为反应安排一个伤害事件(再次通过仅告诉 GES 该事件)。该事件数据中是否会提到伤害的来源仅仅是一个设计决定(也许你不想让伤害听众像治疗咒语或类似的任何方法来找出谁是攻击者,无论原因)。在 Tubmud,我们尽可能多地发送信息,并且没有遇到任何缺点。

现在 GES 将再次调用受害者来接收它自己发送的伤害事件(因为也许其他一些听众会改变伤害的东西,例如减少因止痛药造成的伤害)。对它做出反应,它实际上会降低它的健康。

如果这种健康减少导致死亡,那么它会发送一个死亡事件,因为在我们的理解中,死亡是更实际的事情发生(并且我们先让它发生)。这又是一个通过 GES 发送并再次被受害者接收的事件。如果您决定在伤害事件中不提及攻击者,那么它也不会出现在死亡事件中。所以也许你现在会做出不同的决定;-)

最后,现在,在我的理解中,杀戮不是物理事件,而是对所发生事情的解释。如果攻击事件导致损坏并导致死亡,那么这就是杀戮。所以,严格来说,检测这种情况的正确方法是一种全能的法官,它只注意到所有这些事件,并根据它们的结果决定然后发送一个杀戮事件。

我不确定这些想法是否对您有任何帮助。我只是将其发布为关于我们如何做到这一点的报告。

所以,关于你的问题:

如果您设计一个物理世界的模拟,并希望能够在一系列事件之后决定它们的含义,那么不要过于急于封装数据,试图将其仅粘贴在它所属的位置。攻击者在伤害事件中可能看起来并不重要,所以你可能会想忽略它,但是一旦结果被完整地解释,丢失的数据就会很烦人。毕竟,在现实生活中,警察也可能会发现丢失的数据(因此实际上在现实生活中,造成伤害的信息通常存在于伤害中)。

于 2013-05-26T22:45:13.527 回答