java - 断开长开关

标签 java refactoring

我有这个代码:

public void addSkillXp(SkillType attribute, int value) {
    final SkillDatabaseEntity skillDatabaseEntity = skillValueCache.getEntity();

    switch (attribute) {
        case TWO_HANDED_CRUSHING_WEAPONS:
            skillDatabaseEntity.setTwoHandedCrushingWeaponsXp(value);

            skillMapper.addTwoHandedCrushingWeaponsXp(userEntity.getId(), value);
            break;
        case ONE_HANDED_CRUSHING_WEAPONS:
            skillDatabaseEntity.setOneHandedCrushingWeaponsXp(value);

            skillMapper.addOneHandedCrushingWeaponsXp(userEntity.getId(), value);
            break;
        case TWO_HANDED_AXES:
            skillDatabaseEntity.setTwoHandedAxesXp(value);

            skillMapper.addTwoHandedAxesXp(userEntity.getId(), value);
            break;
        case ONE_HANDED_AXES:
            skillDatabaseEntity.setOneHandedAxesXp(value);

            skillMapper.addOneHandedAxesXp(userEntity.getId(), value);
            break;
        case THROWING_WEAPONS:
            skillDatabaseEntity.setThrowingWeaponsXp(value);

            skillMapper.addThrowingWeaponsXp(userEntity.getId(), value);
            break;
        case FISTFIGHT:
            skillDatabaseEntity.setFistfightXp(value);

            skillMapper.addFistfightXp(userEntity.getId(), value);
            break;
        ...
}

开关已持续超过 20 个案例。 SkillDatabaseEntity 是一个简单的 DAO 类:

public class SkillDatabaseEntity {

    private int twoHandedCrushingWeaponsXp;
    private int oneHandedCrushingWeaponsXp;
    private int twoHandedAxesXp;
    private int oneHandedAxesXp;
    private int throwingWeaponsXp;
    private int fistfightXp;
    private int longswordsXp;
    private int shortswordsXp;
    private int polearmsXp;
    private int daggersXp;
    private int longbowsXp;
    private int showrtbowsXp;
    private int crossbowsXp;
    private int lightArmorXp;
    private int heavyArmorXp;
    private int robeArmorXp;
    private int armorlessDefenseXp;
    private int shieldDefenseXp;
    private int staffsXp;
    private int wandsXp;
    private int spectresXp;
    private int scavengingXp;
    private int cookingXp;

    public int getTwoHandedCrushingWeaponsXp() {
        return twoHandedCrushingWeaponsXp;
    }

    public void setTwoHandedCrushingWeaponsXp(int twoHandedCrushingWeaponsXp) {
        this.twoHandedCrushingWeaponsXp = twoHandedCrushingWeaponsXp;
    }

    public int getOneHandedCrushingWeaponsXp() {
        return oneHandedCrushingWeaponsXp;
    }

    public void setOneHandedCrushingWeaponsXp(int oneHandedCrushingWeaponsXp) {
        this.oneHandedCrushingWeaponsXp = oneHandedCrushingWeaponsXp;
    }

    public int getTwoHandedAxesXp() {
        return twoHandedAxesXp;
    }

    public void setTwoHandedAxesXp(int twoHandedAxesXp) {
        this.twoHandedAxesXp = twoHandedAxesXp;
    }

    public int getOneHandedAxesXp() {
        return oneHandedAxesXp;
    }

    public void setOneHandedAxesXp(int oneHandedAxesXp) {
        this.oneHandedAxesXp = oneHandedAxesXp;
    }

    public int getThrowingWeaponsXp() {
        return throwingWeaponsXp;
    }

    public void setThrowingWeaponsXp(int throwingWeaponsXp) {
        this.throwingWeaponsXp = throwingWeaponsXp;
    }
    ...
}

我需要添加removeSkillXp,但真的想避免这个巨大的开关,而且如果我在这里,我也想改进那个旧的开关。我怎样才能做到这一点?

我的计划是创建一个像这样的新类:

技能修改器:

  • 增加经验(UserEntity,值)
  • decreaseExperience(UserEntity,值)
  • getExperience(UserEntity, 值)
  • getSupportedSkillType()

并为交换机中的每个案例创建此类的实例,将实例添加到映射中(这可以使用 Spring DI 轻松完成)并使用如下内容:

public void addSkillXp(SkillType attribute, int value) {
    skillMap.get(attribute).increaseExperience(userEntity, value);
}

这能行吗?或者有更好的模式可以做吗?

最佳答案

如果将功能从代码移到对象中,事情就会变得容易得多。

例如:

enum SkillType {
    TWO_HANDED_CRUSHING_WEAPONS {
        @Override
        void updateEntity(SkillDatabaseEntity entity, int value) {
            entity.setTwoHandedCrushingWeaponsXp(value);
        }

        @Override
        void mapSkill(SkillMapper mapper, int userId, int value) {
            mapper.addTwoHandedCrushingWeaponsXp(userId, value);

        }
    },
    ONE_HANDED_CRUSHING_WEAPONS {
        @Override
        void updateEntity(SkillDatabaseEntity entity, int value) {
            entity.addOneHandedCrushingWeaponsXp(value);
        }

        @Override
        void mapSkill(SkillMapper mapper, int userId, int value) {
            mapper.addOneHandedCrushingWeaponsXp(userId, value);

        }
    },
    TWO_HANDED_AXES {
        @Override
        void updateEntity(SkillDatabaseEntity entity, int value) {
            entity.setTwoHandedAxesXp(value);
        }
        @Override
        void mapSkill(SkillMapper mapper, int userId, int value) {
            mapper.addTwoHandedAxesXp(userId, value);

        }
    };

    abstract void updateEntity(SkillDatabaseEntity entity, int value);

    abstract void mapSkill(SkillMapper mapper, int userId, int value);
}

public void addSkillXp(SkillType skill, int value) {
    final SkillDatabaseEntity skillDatabaseEntity = skillValueCache.getEntity();
    skill.updateEntity(skillDatabaseEntity, value);
    skill.mapSkill(skillMapper, userEntity.getId(), value);
}

这里addSkillXp变成了只有三行代码。

这样做的另一个好处是所有与技能相关的代码都在同一个enum中。

关于java - 断开长开关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36744588/

相关文章:

java - 在循环中创建具有不同名称的多个对象以存储在数组列表中

ruby-on-rails - `new` 关键字在此 Ruby 方法定义中如何工作?

java - 如何实现Template设计模式?

java - MarkLogic 到 Java & 返回解决方案

java - HashMap 中的部分搜索

java - 使用 JAR 导出图像/文本文件

css - 如何真正找到网站上所有未使用的 css 样式

Java 空条件

c++ - Eclipse CDT 移动文件和重命名文件重构?

java - Spring Data JpaRepository findAll(Iterable<ID> ids) + findAll(Sort 排序)