使用嵌套枚举的重构方法

Refactoring Methods using Nested Enums

我正在从事一个模拟经过大量修改的 DnD 3.5 的项目。现在,我正在研究专业(类,但我不想在那里与 class 混淆),尤其是关于储蓄。现在,我为每个职业都有一个枚举,每个成员都使用一个构造函数来指定每种保存是好还是坏,这在嵌套枚举中表示。但是,计算修正值的方法基本相同,只是它们在不同的豁免检定上使用 switch

有没有一种方法可以重构方法以接受父枚举作为方法的参数之一,然后检查嵌套枚举的值?

public enum Profession {
    BARBARIAN   (WillSave.POOR, FortitudeSave.GOOD, ReflexSave.POOR),
    BARD        (WillSave.GOOD, FortitudeSave.POOR, ReflexSave.GOOD),
    CLERIC      (WillSave.GOOD, FortitudeSave.GOOD, ReflexSave.POOR);


    private static int goodSaveModifier(int level) {
        return ((level / 2) + 2);
    }

    private static int poorSaveModifier(int level) {
        return (level / 3);
    }



    /**
     * Generates the given ProfessionType
     *
     * @param wil <code>WillSave.STRONG</code> if profession has a good will save, or
     * <code>POOR</code> otherwise
     * @param fort <code>FortitudeSave.STRONG</code> if profession has a good fortitude save, or
     * <code>POOR</code> otherwise
     * @param ref <code>ReflexSave.STRONG</code> if profession has a good reflex save, or
     * <code>POOR</code> otherwise
     */
    Profession(WillSave wil, FortitudeSave fort, ReflexSave ref) {
        will = wil;
        fortitude = fort;
        reflex = ref;
    }


    /**
     * Calculates the Profession's Fortitude modifier.
     *
     * @param level Character's current level
     * @return Profession's modifier of the WillSave save
     * @throws IndexOutOfBoundsException If saving throw strength isn't valid
     */
    public int willModifier(int level) {
        int modifier;

        switch(will) {
            case GOOD:
                modifier = goodSaveModifier(level);
                break;
            case POOR:
                modifier = poorSaveModifier(level);
                break;
            default:
                throw new IndexOutOfBoundsException("Save type " + will.name() + " doesn't exist.");
        }

        return modifier;
    }

    /**
     * Calculates the Profession's Fortitude modifier.
     *
     * @param level Character's current level
     * @return Profession's modifier of the FortitudeSave save
     * @throws IndexOutOfBoundsException If saving throw strength isn't valid
     */
    public int fortitudeModifier(int level) {
        int modifier;

        switch(fortitude) {
            case GOOD:
                modifier = goodSaveModifier(level);
                break;
            case POOR:
                modifier = poorSaveModifier(level);
                break;
            default:
                throw new IndexOutOfBoundsException("Save type " + fortitude.name()
                                                            + " doesn't exist.");
        }

        return modifier;
    }

    /**
     * Calculates the Profession's Reflex modifier.
     *
     * @param level Character's current level
     * @return Profession's modifier of the ReflexSave save
     * @throws IndexOutOfBoundsException If saving throw strength isn't valid
     */
    public int reflexModifier(int level) {
        int modifier;

        switch(reflex) {
            case GOOD:
                modifier = goodSaveModifier(level);
                break;
            case POOR:
                modifier = poorSaveModifier(level);
                break;
            default:
                throw new IndexOutOfBoundsException("Save type " + reflex.name()
                                                            + " doesn't exist.");
        }

        return modifier;
    }


    private final WillSave will;
    private final FortitudeSave fortitude;
    private final ReflexSave reflex;




    private enum WillSave {
        GOOD, POOR;
    }

    private enum FortitudeSave {
        GOOD, POOR;
    }

    private enum ReflexSave {
        GOOD, POOR;
    }
}

我能想到的就是有另一个嵌套的枚举,让我们以 SavingThrow.WILL 为例,我想不出在这种情况下如何指定自签名以来参数中的哪个抛出然后会像 calculateModifier(SavingThrow save, int level) : int 这样的东西,它不会工作。无论如何,这是我的尝试,尽管它显然只会抛出诸如 WILL 之类的保存而不是诸如 GOOD 之类的值。有没有一种方法可以干净地重构这样的东西?

public int calculateModifier(SavingThrow save, int level) {
    int modifier;

    switch(save) {
        case GOOD:
            modifier = goodSaveModifier(level);
            break;
        case POOR:
            modifier = poorSaveModifier(level);
            break;
        default:
            throw new IndexOutOfBoundsException("Save type " + save.name()
                                                        + " doesn't exist.");
    }

    return modifier;
}


private final SavingThrow.WILL will;
private final SavingThrow.FORTITUDE fortitude;
private final SavingThrow.REFLEX reflex;



private enum SavingThrow {
    WILL {
        GOOD, POOR;
    },

    FORTITUDE {
        GOOD, POOR;
    },

    REFLEX {
        GOOD, POOR;
    };
}

我不确定为什么您有 3 个相同的枚举,但名称不同。这是重构后的代码:

public enum Profession {
    BARBARIAN   (Save.POOR, Save.GOOD, Save.POOR),
    BARD        (Save.GOOD, Save.POOR, Save.GOOD),
    CLERIC      (Save.GOOD, Save.GOOD, Save.POOR);

    private final Save will;
    private final Save fortitude;
    private final Save reflex;

    Profession(Save will, Save fortitude, Save reflex) {
        this.will = will;
        this.fortitude = fortitude;
        this.reflex = reflex;
    }

    public int willModifier(int level) {
        return will.modifier.apply(level);
    }

    public int fortitudeModifier(int level) {
        return fortitude.modifier.apply(level);
    }

    public int reflexModifier(int level) {
        return reflex.modifier.apply(level);
    }

    private enum Save {

        GOOD(level -> level / 2 + 2),
        POOR(level -> level / 3);

        private final Function<Integer, Integer> modifier;

        Save(Function<Integer, Integer> modifier) {
            this.modifier = modifier;
        }

    }

}

这对你有用吗?