跨多个类版本的多态函数有什么好的python设计模式:交叉点,联合和差异?

时间:2018-02-06 22:01:22

标签: python python-2.7

我有一组非常相似的对象,我为每个对象显式编写相同函数的当前方法不能很好地扩展,因为我将新对象添加到游戏区域。

我的每个武器都有一个属性字典:

class Sword(Item):
    def __init__():
        self.properties = {"Blade": True, "Attack": 30, "Defense": 5, "Type": "standard"}

class Dagger(Item):
    def __init__():
        self.properties = {"Blade": True, "Attack": 20, "Type": "stealth"}

class Pistol(Item):
    def __init__(self):
        self.properties = {"Firearm": True, "Attack": 20, "Type": "stealth"}

class Wooden_shield(Item):
    def __init__():
        self.properties = {"Shield": True, "Defense": 30, "Type": "standard"}

在我的战斗代码中,我想做这样的事情:

best_attack_item = None
for item in inventory:
    attack_power = item.properties.get("Attack")
    if best_attack_item:
        if attack_power > best_attack_item.get("Attack"):
            best_attack_item = item


best_attack_item.attack() # I would like attack() to automatically do what is correct

所以这是我的虚拟解决方案。如何让它更好地扩展?我正在处理超过30个攻击项目,并且它会随着时间的推移而不断增长。我不想在每次变化时多次编写和维护攻击代码。

不良解决方案

class Sword(Item):
    def __init__(self):
        self.properties = {"Blade": True, "Attack": 30, "Defense": 5, "Type": "standard"}
    def attack(self):
        print("attacking with blade!")

class Dagger(Item):
    def __init__(self):
        self.properties = {"Blade": True, "Attack": 20, "Type": "stealth"}
    def attack(self):
        print("attacking with blade!")

class Pistol(Item):
    def __init__(self):
        self.properties = {"Firearm": True, "Attack": 20, "Type": "stealth"}
    def attack(self):
        print("Firing!")

class Wooden_shield(Item):
    def __init__(self):
        self.properties = {"Shield": True, "Defense": 30, "Type": "standard"}

我在想一种跟踪所有属性子集的方法可能如下所示。我喜欢这个,因为我认为管理这些集更容易。然而,关于它的一些事情仍然感觉不好。这怎么可能更好?

解决方案不太糟糕但仍不满意

_CAN_FIRE = {"Firearm": True}
_HAS_BLADE = {"Blade": True}

@poly_loader(Item, _CAN_FIRE)
class can_fire_extensions(Item):
    def attack(self):
        print("Firing!")

@poly_loader(Item, _HAS_BLADE)
class has_blade_extensions(Item):
    def attack(self):
        print("Attacking with blade!")

1 个答案:

答案 0 :(得分:0)

有几种方法可以解决这个问题......

使用继承,包括多重继承

除了将Item继承为WeaponShieldWeapon继承为BladeFirearm之外,您还可以单独创建只有一种方法的类,并期望有某些属性。

class Shootable(object):
    def aim(self):
        self.find_target()
    def fire(self):
        self.attack()
        # some more stuff

然后Pistol看起来像这样:

class Pistol(Item, Shootable):
    def __init__(self):
        pass # Whatever goes here

根本不要使用课程

课程根本没有解决的一件事:跨领域的问题。想象一下,你有一个既有刀片也有盾牌的东西。或具有隐身效果和元素效果的武器 - 两者都适用于attack动作。

据我所知,您的商品基本上只是数据容器。你可能最好在功能中保留功能。您可以使用词典通过调度表定义规则。例如:

ItemRules = {
    ('Blade', True): blade_behavior,
    ('Firearm', True): firearm_behavior,
    ('Shield', True): shield_behavior,
    ('Type', 'stealth'): stealth_behavior
}

blade_behaviorfirearm_behaviorshield_behavior都是定义适当行为的函数或类或其他内容。因此,您的规则引擎会匹配'Blade' True的项目定义,然后为该方案运行相应的代码。这样做的好处是,如果一个项目符合多个规则,它可以运行所有这些规则的行为。这使得添加FirearmBlade的项目变得微不足道 - 只要您测试了该组合即可。您可能最终需要在规则引擎中使用优先级系统来正确解决奇怪的情况,但这是您在不断添加到系统时必须弄明白的事情。

这种方法的一大优势是,您可以将项目数据与代码完全分开,从而可以轻松添加仅略有不同的新项目。

如果你发现这个解释令人困惑,我可以想出一个更加充实的实现的Github要点来解释我的意思。