【问题标题】:What are some methods of dynamic validation for a generic class?泛型类有哪些动态验证方法?
【发布时间】:2010-08-24 16:24:28
【问题描述】:

所以基本上,标题听起来比实际问题要花哨。

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

例如:

成就 - 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中使用函数指针吗?我是这门语言的新手 :(

【问题讨论】:

  • java中没有函数指针。
  • @Shengyuan Lu 我想他/她知道java中没有函数指针。 @FlyingStreudel 我的建议是等待 Java 7 闭包。

标签: java android eclipse algorithm achievements


【解决方案1】:

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

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
    }
}

EDIT另一个防止继承(和使用组合)的选项是使用类似于strategy pattern的东西。

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; }
});

【讨论】:

  • 是的,这是我能想出的唯一解决方案,但我试图找到一种不需要抽象基类的方法:(如果一切都失败了,我将回到这个。编辑错误不是抽象,但是是的..
  • @FlyingStreudel:你为什么要避免这种情况?
  • 这样做是为了好玩,因为我是一名编程技术专家。我想看看是否有一种方法可以实现相同的功能而无需子类型
  • 基本上我不想限制输入的类型。因此,如果我想添加一种以前从未想过的全新成就类型,我可以做到,而无需添加新的成就子类型。
  • @FlyingStreudel:那么你可能需要一些基本的语言/解释器。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-26
    • 2019-04-11
    • 2017-12-23
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    相关资源
    最近更新 更多