1

pygame几年前我做了一个游戏。它有效,但不是最好的编码风格,而且有很多经典的代码味道。我最近把它捡回来了,这次我试图用更多的纪律来重构它。

一个很大的代码异味是我有一个巨大的类 GameObject,它继承自pygame.sprite.DirtySprite它有很多与以下相关的代码:

  • 移动精灵的各种方式
  • 动画精灵的各种方法
  • 爆炸精灵的各种方法
  • 等等

我认为精灵的行为方式越疯狂,代码重复越多,更改变得越来越困难。因此,我开始将功能分解为许多较小的类,然后在创建对象时将它们传递进去:

class GameObject(DirtySprite):
    def __init__(initial_position, mover_cls, imager_cls, exploder_cls):
        self.mover = mover(self, initial_position)
        self.imager = imager(self)
        self.exploder = exploder(self)

...
spaceship = GameObject(pos, CrazyMover, SpaceshipImager, BasicExploder)

随着我将越来越多的代码分解到这些帮助类中,代码肯定更好、更灵活并且重复更少。但是,对于每种类型的辅助类,参数的数量越来越多。创建精灵变成了一件苦差事,而且代码很丑陋。所以,在另一个重构过程中,我创建了一堆非常小的类来进行组合:

class GameObjectAbstract(MoverAbstract, ImagerAbstract, \
                         ExploderAbstract, DirtySprite):
    def __init__(self, initial_position):
        ...
...
class CrazySpaceship(CrazyMover, SpaceshipImager, BasicExploder, GameObjectAbstract):
    pass  # Many times, all the behavior comes from super classes

...
spaceship = CrazySpaceship(pos)

我更喜欢这种方法。这是一种常见的方法吗?在小类中分解所有逻辑似乎具有相同的好处,但是创建对象要干净得多。

但是,这种方法不是动态的。例如,我不能在运行时决定新的混搭。然而,这并不是我真正在做的事情。虽然我做了很多混搭,但使用类语句静态定义它们似乎没问题。

当谈到未来的可维护性和重用性时,我是否遗漏了什么?我听说组合比继承好,但这感觉就像我在使用继承来做组合——所以我觉得这样还可以。

我应该使用不同的模式吗?

4

1 回答 1

2

没关系,如果你能很好地分离行为 -

只是它根本不是“组合”——它是多重继承,使用我们所谓的“混合类”:混合类大致是一个提供特定行为的类,可以与其他类组合。

如果您super 正确使用 Python,那可能是最好的方法。(如果您正在设法创建游戏对象,基本上只是定义类名和它使用的 mixin 类,那实际上是一个非常好的方法)

顺便说一句,如果您想在运行时使用此方法创建新类,它也是可能的 - 只需使用调用type来创建新类,而不是class语句:

class CrazySpaceship(CrazyMover, SpaceshipImager, BasicExploder, GameObjectAbstract):
    pass  # Many times, all the behavior comes from super classes

在 Python 中相当于:

CrazySpaceShip = type('CrazySpaceShip', (CrazyMover, SpaceshipImager, BasicExploder, GameObjectAbstract), {})

您用作第二个参数的元组可以是运行时构建的任何序列。

于 2017-04-30T05:42:13.490 回答