You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java游戏可收集物品系统避免违反开闭原则的设计模式咨询

核心问题分析

当前实现的核心矛盾是收集逻辑和具体职业类型硬绑定,强制类型转换导致新增兼容职业时必须修改Spell类代码,违反开闭原则。

可选解决方案

方案1:能力标记接口(轻量改造成本,适合大多数场景)

通过接口标记拥有特殊收集能力的职业,完全避免和具体职业类耦合,新增兼容职业无需修改现有物品代码:

  1. 定义施法者能力接口
public interface SpellCaster {
    Set<Collectable> getSpellBook();
}
  1. 所有可收集法术的职业实现该接口
public class Wizard extends Character implements SpellCaster {
    private Set<Collectable> spellBook = new HashSet<>();

    @Override
    public Set<Collectable> getSpellBook() {
        return spellBook;
    }
}

// 后续新增Warlock职业直接实现接口即可,无需修改Spell代码
public class Warlock extends Character implements SpellCaster {
    private Set<Collectable> spellBook = new HashSet<>();

    @Override
    public Set<Collectable> getSpellBook() {
        return spellBook;
    }
}
  1. 修改Spell类的收集逻辑,仅校验接口实现,无需硬转具体职业类
public class Spell extends Collectable {
    @Override
    public void collect(Character character) {
        // Java 16+支持模式匹配写法,低版本可手动强转SpellCaster
        if (character instanceof SpellCaster caster) {
            caster.getSpellBook().add(this);
            return;
        }
        // 自定义不兼容逻辑:比如提示无法收集、自动丢弃等
        throw new IllegalArgumentException(character.getClass().getSimpleName() + " 无法收集法术类道具");
    }
}

方案2:访问者模式(适合收集逻辑复杂的重交互场景)

如果后续大量物品都有职业专属收集/使用逻辑,可通过访问者模式彻底消除类型转换,实现双向解耦:

  1. 定义访问者接口
public interface CollectableVisitor {
    void visit(Wizard wizard);
    void visit(Warrior warrior);
    // 新增职业时仅需在这里添加对应visit方法
}
  1. 修改Character基类,增加访问入口
public abstract class Character {
    public Set<Collectable> inventory = new HashSet<>();
    public abstract void accept(CollectableVisitor visitor);

    public void collect(Collectable collectable) {
        collectable.collect(this);
    }
}
  1. 各个职业实现访问入口
public class Wizard extends Character {
    public Set<Collectable> spellBook = new HashSet<>();
    @Override
    public void accept(CollectableVisitor visitor) {
        visitor.visit(this);
    }
}

public class Warrior extends Character {
    @Override
    public void accept(CollectableVisitor visitor) {
        visitor.visit(this);
    }
}
  1. Collectable基类实现访问者接口
public abstract class Collectable implements CollectableVisitor {
    public abstract void collect(Character character);
}
  1. Spell类实现无类型转换的收集逻辑
public class Spell extends Collectable {
    @Override
    public void collect(Character character) {
        character.accept(this);
    }

    @Override
    public void visit(Wizard wizard) {
        wizard.spellBook.add(this);
    }

    @Override
    public void visit(Warrior warrior) {
        throw new IllegalArgumentException("战士无法收集法术类道具");
    }
}

选型建议

  • 仅少数道具存在职业收集限制时选方案1,代码量小、维护成本低
  • 大量道具存在职业专属交互逻辑时选方案2,可扩展性更强

内容的提问来源于stack exchange,提问作者Mangos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:36:07