链接类装饰符来扩展游戏物品的能力

2024-09-30 01:19:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为我的python课程编写一个小游戏,我想集成一个库存和项目系统。物品提供的可能性是可变的(武器、任务物品、消耗品等等)。你知道吗

我已经阅读了这篇关于pattern decoratorgoogle translated in english)的教程(法语),我附带了以下内容: (我用的是Python3)

class Item(object):

    def __init__(self, caracts=None, inventory=None):
        self.caracts = {}
        if caracts:
            self.caracts = caracts
        self.inventory = inventory


class ItemDecorator(Item):

    def __init__(self, item):
        super().__init__()
        self.item = item
        self.caracts = item.caracts


class Consumable(ItemDecorator):

    def __init__(self, item, amount=1):
        super().__init__(item)
        self._amount = 0
        self.amount = amount

    @property
    def amount(self):
        return self._amount

    @amount.setter
    def amount(self, value):
        self._amount = max(0, value)
        if self._amount == 0 and self.item.inventory:
            self.item.inventory.remove(self)

    @amount.deleter
    def amount(self):
        del self._amount


class Usable(ItemDecorator):

    def __init__(self, item, action=None, consumable=None):
        if not action:
            action = lambda *args, **kwargs: None
        self._use = action
        self.consumable = consumable

    def use(self, *args, **kwargs):
        if self.consumable and self.consumable.amount <= 0:
            raise CantBeUsedException("There is no consumable")
        else:
            if self.consumable:
                self.consumable.amount -= 1
            self._use(*args, **kwargs)

我的想法是能够做到这一点:

potion = Usable(Consumable(Item(), 3), use_potion)
print("isinstance(potion.item, Consumable): {}".format(
    isinstance(potion.item, Consumable)))
potion.consumable = potion.item
for dummy in range(4):
    try:
        potion.use()
    except CantBeUsedException as e:
        print("Expected exception: {}".format(e))

但我的问题来了,第四行。可用的potion使用的消耗品应该是potion本身。但是potion失去了它的消耗能力,只有potion.item拥有它。更糟糕的是,我给我的装饰师打电话的顺序很重要。potion = Consumable(Usable(Item(), use_potion), 3)引导我去做potion.item.use(),总是这个项目让我烦恼。你知道吗

我怎样才能简化这个?知道一个可用的不一定会消耗自己,甚至一些东西。事实上,我希望能够做到这一点,无论哪个装饰师被称为第一:

potion = Consumable(Usable(Item(), use_potion), 3)
potion.consumable = potion
potion.use()

我没能为我的问题找到一个干净的解决办法。下面是我想到的所有问题: *这个装饰图案适合吗?(在我看来是这样,但我可能错了) *如果不是这样,在你看来,接口系统(因此,具有多重遗产)不是更好的解决方案吗? *我犯了什么错被困在这里?你知道吗

  • 如何使这个系统真正简单,同时仍然是可扩展的。为此,我考虑以下解决方案:

    class ItemDecorator(Item):
    
            def __init__(self, item):
            super().__init__()
            self.item = item
            self.caracts = item.caracts
            if hasattr(item, "amount"):
                self.amount = item.amount
            if hasattr(item, "use"):
                self.use = item.use
    

    但是这样做,我就失去了Decorator模式的所有可扩展性了吗?事实上,每次我想要创建一个非常复杂的decorator时,我都需要更新itemdecommator。这样,我就不会失去装饰图案的所有优点了吗?

非常感谢你的帮助


Tags: selfnoneifinitusedefitemamount
1条回答
网友
1楼 · 发布于 2024-09-30 01:19:28

现在您的类布局相当扭曲,而且Usable(Consumable(Item(), 3), use_potion)看起来不像pythonic。你知道吗

我稍微重新设计一下系统:

class ItemCapability:
    pass


class Consumable(ItemCapability):
    def __init__(self, amount):
        super().__init__()
        self.amount = amount


class Usable(ItemCapability):
    pass


class Item:
    def __init__(self, name):
        self.name = name
        self.capabilities = {}

    def make(self, capability):
        assert isinstance(capability, ItemCapability)
        assert capability.__class__ not in self.capabilities

        self.capabilities[capability.__class__] = capability

    def has(self, capability_cls):
        try:
            return self.capabilities[capability_cls]
        except KeyError:
            return False


potion = Item('potion')
potion.make(Usable())
potion.make(Consumable(amount=10))

print(potion.has(Usable))
print(potion.has(Consumable))

这样,您就有了一个非常容易理解的类系统,以及查询您的项以获取功能的简单方法。你知道吗

相关问题 更多 >

    热门问题