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

基于依赖倒置原则,如何访问子类独有的非接口方法?

问题分析与解决方案

问题背景

现有代码结构中:

  • Weapon接口定义通用方法A()
  • Sword、Bow实现Weapon,分别拥有独有方法B()、C()
  • BattleService依赖Weapon接口,仅能调用通用方法A(),无法访问子类独有方法

需要在遵循依赖倒置原则(高层模块依赖抽象,而非具体实现)的前提下,让BattleService可以调用B()和C()。


可行方案一:基于接口隔离+依赖倒置的扩展实现

通过拆分抽象接口,为不同武器定义专属抽象,同时让BattleService依赖这些抽象而非具体类,既满足依赖倒置,又能安全访问子类独有方法。

代码实现

// 基础武器接口,保留通用方法
public interface Weapon {
    void A();
}

// 剑专属接口,继承基础接口并定义独有方法
public interface SwordWeapon extends Weapon {
    void B();
}

// 弓专属接口,继承基础接口并定义独有方法
public interface BowWeapon extends Weapon {
    void C();
}

// Sword实现剑专属接口
public class Sword implements SwordWeapon {
    @Override
    public void A() {
        System.out.println("Sword A");
    }

    @Override
    public void B() {
        System.out.println("Sword B");
    }
}

// Bow实现弓专属接口
public class Bow implements BowWeapon {
    @Override
    public void A() {
        System.out.println("Bow A");
    }

    @Override
    public void C() {
        System.out.println("Bow C");
    }
}

// BattleService通过重载构造方法和专属方法,依赖不同抽象接口
public class BattleService {
    private Weapon weapon;
    private SwordWeapon swordWeapon;
    private BowWeapon bowWeapon;

    // 通用构造方法,适配所有武器
    public BattleService(Weapon weapon) {
        this.weapon = weapon;
    }

    // 剑专属构造方法,依赖剑的抽象接口
    public BattleService(SwordWeapon swordWeapon) {
        this.weapon = swordWeapon;
        this.swordWeapon = swordWeapon;
    }

    // 弓专属构造方法,依赖弓的抽象接口
    public BattleService(BowWeapon bowWeapon) {
        this.weapon = bowWeapon;
        this.bowWeapon = bowWeapon;
    }

    // 通用方法调用
    public void A() {
        weapon.A();
    }

    // 剑独有方法调用,仅注入剑时可用
    public void useSwordSkillB() {
        if (swordWeapon != null) {
            swordWeapon.B();
        } else {
            throw new UnsupportedOperationException("当前武器不是剑,无法调用方法B");
        }
    }

    // 弓独有方法调用,仅注入弓时可用
    public void useBowSkillC() {
        if (bowWeapon != null) {
            bowWeapon.C();
        } else {
            throw new UnsupportedOperationException("当前武器不是弓,无法调用方法C");
        }
    }
}

// 客户端测试
public class Main {
    public static void main(String[] args) {
        // 使用剑
        SwordWeapon sword = new Sword();
        BattleService swordBattle = new BattleService(sword);
        swordBattle.A();
        swordBattle.useSwordSkillB();

        // 使用弓
        BowWeapon bow = new Bow();
        BattleService bowBattle = new BattleService(bow);
        bowBattle.A();
        bowBattle.useBowSkillC();
    }
}

方案说明

  1. 接口隔离:为不同武器定义专属抽象接口,既继承通用方法,又声明独有方法,符合单一职责原则。
  2. 依赖倒置:BattleService依赖的是抽象接口而非具体类,高层模块不依赖底层实现。
  3. 安全访问:通过专属构造方法和方法,确保只有注入对应武器抽象时才能调用独有方法,避免类型转换风险。

可行方案二:访问者模式(适合复杂武器体系)

如果后续会扩展更多武器类型,访问者模式可以更好地解耦武器与操作逻辑:

代码实现

// 定义访问者接口,声明对不同武器的操作
public interface WeaponVisitor {
    void visitSword(Sword sword);
    void visitBow(Bow bow);
}

// 修改基础武器接口,添加接受访问的方法
public interface Weapon {
    void A();
    void accept(WeaponVisitor visitor);
}

// 修改Sword类,实现accept方法
public class Sword implements Weapon {
    @Override
    public void A() {
        System.out.println("Sword A");
    }

    public void B() {
        System.out.println("Sword B");
    }

    @Override
    public void accept(WeaponVisitor visitor) {
        visitor.visitSword(this);
    }
}

// 修改Bow类,实现accept方法
public class Bow implements Weapon {
    @Override
    public void A() {
        System.out.println("Bow A");
    }

    public void C() {
        System.out.println("Bow C");
    }

    @Override
    public void accept(WeaponVisitor visitor) {
        visitor.visitBow(this);
    }
}

// BattleService集成访问者逻辑,实现对不同武器的独有方法调用
public class BattleService implements WeaponVisitor {
    private Weapon weapon;

    public BattleService(Weapon weapon) {
        this.weapon = weapon;
    }

    public void A() {
        weapon.A();
    }

    // 统一入口调用独有技能
    public void useUniqueSkill() {
        weapon.accept(this);
    }

    @Override
    public void visitSword(Sword sword) {
        sword.B();
    }

    @Override
    public void visitBow(Bow bow) {
        bow.C();
    }
}

// 客户端测试
public class Main {
    public static void main(String[] args) {
        BattleService swordBattle = new BattleService(new Sword());
        swordBattle.A();
        swordBattle.useUniqueSkill(); // 调用Sword的B方法

        BattleService bowBattle = new BattleService(new Bow());
        bowBattle.A();
        bowBattle.useUniqueSkill(); // 调用Bow的C方法
    }
}

方案说明

  • 访问者模式将武器的独有操作从武器类中分离,BattleService作为访问者实现对不同武器的方法调用。
  • 遵循依赖倒置原则:Weapon接口定义accept方法,BattleService依赖Weapon和WeaponVisitor抽象,不直接依赖具体武器类。
  • 扩展性好:新增武器时,只需扩展WeaponVisitor并添加对应visit方法,无需修改现有BattleService核心逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:06:22