1

所以基本上这个标题听起来比实际问题更有趣。

我正在编写一个应用程序,我想在其中实现一个成就系统。如果我将所有成就都创建为通用类的实例,我如何编写一个方法来验证这些成就(即确定用户是否达到或超过目标),当完成的壮举类型可能不同时,条件的数量要满足的条件可能会有所不同,验证的类型可能会有所不同?

例如:

成就 - 10,000 分!
类型 - 总分值
(X) - 10,000
条件 - 1
验证 - 大于 X

对比

成就 - 超碎片
类型 - 击杀
值 (X) - 10
类型 - 时间
值 (Y) - 10 秒
条件 - 2
验证 - 至少 X 在小于 Y

我试图避免为每个成就硬编码验证函数,因为它们主要是通用的,唯一的区别是它们的验证方式。

就像成就类看起来像

public class Achievement 
{
    boolean locked;
    String name;
    String desc;

    public Achievement(string n, string d)
    {
        //ctor code
    }
}

我正在想办法在没有函数指针的情况下做到这一点,但我失败了。另外,你甚至可以在java中使用函数指针吗?我是这门语言的新手:(

4

2 回答 2

2

我认为正确的做法是为每个成就设置一个验证方法:

public abstract class Achievement {
    //...name, etc
    public boolean isSatisfied(Data byPlayerData);
}

但这并不能阻止您提供一些具体的实现并使用参数对其进行配置。

public class ZombieKillingAchievement extends Achievement {
     private final int numKills;
     public ZombieKillingAchievement(String name, int numKills) {
         this.numKills = numKills;
     }
     public boolean isSatisfied(Data userData) {
         return userData.getZombieKills() >= numKills;
     }
}

//...
registerAchievement(new ZombieKillingAchievement("Zombie Master", 100));
registerAchievement(new ZombieKillingAchievement("Zombie Tamer", 50));

//... on user data change
for ( Achievement a : registeredAchievements ) {
    if ( a.isSatisfied() ) {
        //show congratulatory message
    }
}

编辑防止继承(和使用组合)的另一个选项是使用类似于策略模式的东西。

public class Achievement {
    //...name, etc
    private final AchievementValidator validator;
}

public interface AchievementValidator {
    public boolean isSatisfied(Data userData);
}

当与匿名内部类一起使用时,它几乎是在使用函数指针

registerAchievement(new Achievement("Zombie Killer", new AchievementValidator() {
    public boolean isSatisfied(Data data) { return data.getZombieKills() >= 50; }
});
于 2010-08-24T16:33:45.347 回答
1

Java(以及通常在任何面向对象语言中)中的函数指针通常由多态对象替换。

关于不对验证进行硬编码,我认为为此编写规则引擎不值得,工作量会大得多。可以做的是将相同类型的成就与具有不同阈值的字段统一为同一类的对象。

于 2010-08-24T16:39:01.880 回答