适用于类版本集合的Python多态函数设计模式及武器功能扩展咨询
嘿,这两个问题都是Python代码复用与扩展性领域的典型痛点,我来给你拆解下具体的解决方案:
一、跨多版本类集合的多态函数设计
针对不同版本类的集合操作(交集、并集、差集),核心思路是让代码依赖抽象而非具体实现,推荐两种模式:
1. 抽象基类(ABC)+ 多态实现
定义一个统一的抽象集合操作接口,不同版本的集合类继承并实现具体逻辑,调用时只需依赖抽象接口,无需关心底层版本差异。
from abc import ABC, abstractmethod class BaseCollectionOps(ABC): @abstractmethod def intersect(self, other): pass @abstractmethod def union(self, other): pass @abstractmethod def difference(self, other): pass # 版本1:用集合存储,直接调用集合运算符 class V1Collection(BaseCollectionOps): def __init__(self, items): self.items = set(items) def intersect(self, other): return self.items & other.items def union(self, other): return self.items | other.items def difference(self, other): return self.items - other.items # 版本2:用列表存储,需保留元素顺序 class V2Collection(BaseCollectionOps): def __init__(self, items): self.items = list(items) def intersect(self, other): return [x for x in self.items if x in other.items] def union(self, other): return self.items + [x for x in other.items if x not in self.items] def difference(self, other): return [x for x in self.items if x not in other.items]
新增版本时,只需继承BaseCollectionOps并实现三个方法即可,调用方代码完全无需修改。
2. 策略模式
如果不同版本的集合操作逻辑差异极大(比如有的需要去重、有的要保留顺序、有的要过滤特定元素),可以把操作逻辑封装成独立策略类,通过上下文类动态切换策略。
class CollectionStrategy(ABC): @abstractmethod def intersect(self, a, b): pass @abstractmethod def union(self, a, b): pass class V1Strategy(CollectionStrategy): def intersect(self, a, b): return set(a) & set(b) def union(self, a, b): return set(a) | set(b) class V2Strategy(CollectionStrategy): def intersect(self, a, b): # 保留原始列表的元素顺序 return [x for x in a if x in b] def union(self, a, b): # 去重但保留顺序 seen = set(a) return a + [x for x in b if x not in seen] class CollectionContext: def __init__(self, strategy: CollectionStrategy): self.strategy = strategy def intersect(self, a, b): return self.strategy.intersect(a, b) def union(self, a, b): return self.strategy.union(a, b) # 使用示例 v1_ctx = CollectionContext(V1Strategy()) print(v1_ctx.intersect([1,2,3], [2,3,4])) # 输出 {2,3} v2_ctx = CollectionContext(V2Strategy()) print(v2_ctx.intersect([1,2,3], [2,3,4])) # 输出 [2,3]
二、武器系统的扩展性优化
针对30+武器且持续增长的场景,核心是把重复的攻击逻辑抽象出来,让武器只负责配置和特有逻辑,推荐三种方案:
1. 模板方法模式 + 基类抽象
定义一个Weapon基类,实现通用攻击流程(检查弹药、计算伤害、触发特效等),把可变部分抽象成钩子方法,子类只需配置properties或重写钩子方法。
class Weapon: def __init__(self, properties): self.properties = properties # 比如 {"damage":10, "damage_type":"fire", "current_ammo":20} def attack(self, target): # 通用攻击流程:固定步骤,可变部分通过钩子方法处理 if not self._check_ammo(): print("弹药不足!") return base_damage = self._calculate_base_damage() modified_damage = self._apply_damage_modifier(base_damage, target) target.take_damage(modified_damage) self._trigger_special_effect(target) self._consume_ammo() # 通用方法,可通过properties配置 def _check_ammo(self): return self.properties.get("current_ammo", float("inf")) > 0 def _calculate_base_damage(self): return self.properties.get("damage", 0) * self.properties.get("multiplier", 1) # 钩子方法:处理伤害类型修正,子类可重写 def _apply_damage_modifier(self, damage, target): dmg_type = self.properties.get("damage_type") if dmg_type == "fire" and target.weakness == "fire": return damage * 1.5 elif dmg_type == "ice" and target.resistance == "ice": return damage * 0.5 return damage # 钩子方法:触发特效,可通过properties配置 def _trigger_special_effect(self, target): effect = self.properties.get("special_effect") if effect == "poison": target.apply_debuff("poison", self.properties.get("poison_dmg", 2), duration=3) def _consume_ammo(self): if "current_ammo" in self.properties: self.properties["current_ammo"] -= 1 # 新增武器只需配置properties,无需写attack方法 fire_sword = Weapon({ "damage":15, "damage_type":"fire", "special_effect":None }) ice_bow = Weapon({ "damage":12, "damage_type":"ice", "current_ammo":30, "special_effect":"slow" })
2. 数据驱动 + 策略模式
如果武器攻击逻辑差异极大(近战/远程/AOE),可以把攻击逻辑封装成独立策略类,武器对象只需组合策略和配置。
class AttackStrategy(ABC): @abstractmethod def execute(self, weapon, target): pass class MeleeAttack(AttackStrategy): def execute(self, weapon, target): # 近战逻辑:无距离限制,直接计算伤害 damage = weapon.properties["damage"] * weapon.properties.get("strength", 1) target.take_damage(damage) class RangedAttack(AttackStrategy): def execute(self, weapon, target): # 远程逻辑:检查距离和弹药 if weapon.properties["current_ammo"] == 0: return if target.distance > weapon.properties["max_range"]: print("超出射程!") return damage = weapon.properties["damage"] * weapon.properties.get("accuracy", 1) target.take_damage(damage) weapon.properties["current_ammo"] -= 1 class Weapon: def __init__(self, properties, attack_strategy: AttackStrategy): self.properties = properties self.attack_strategy = attack_strategy def attack(self, target): self.attack_strategy.execute(self, target) # 新增武器:组合策略+配置 fire_axe = Weapon( {"damage":20, "strength":1.2}, MeleeAttack() ) magic_staff = Weapon( {"damage":18, "max_range":15, "current_ammo":25}, RangedAttack() )
3. 混入(Mixin)类复用通用功能
如果部分武器有共同附加功能(带毒、吸血),用Mixin注入功能,避免重复代码。
class PoisonMixin: def apply_poison(self, target): poison_dmg = self.properties.get("poison_dmg", 3) target.add_debuff("poison", poison_dmg, duration=3) class LifestealMixin: def steal_life(self, damage_dealt): self.properties["current_health"] += damage_dealt * 0.2 # 带毒的匕首:继承Weapon+PoisonMixin class PoisonDagger(Weapon, PoisonMixin): def attack(self, target): super().attack(target) self.apply_poison(target) # 吸血的弓:继承Weapon+LifestealMixin class LifestealBow(Weapon, LifestealMixin): def attack(self, target): original_health = target.health super().attack(target) damage_dealt = original_health - target.health self.steal_life(damage_dealt)
总结
- 跨版本集合操作:优先用ABC+多态(逻辑差异小)或策略模式(逻辑差异大),保证代码对扩展开放、对修改关闭。
- 武器系统:核心是抽象通用逻辑,用配置/策略处理差异,模板方法适合流程固定的场景,策略模式适合逻辑差异大的场景,Mixin适合功能组合。新增武器时,大部分情况只需编写配置或组合已有组件,无需重复编写攻击代码。
内容的提问来源于stack exchange,提问作者SwimBikeRun
相关产品推荐
相关产品推荐

