开发者

What are some methods of dynamic validation for a generic class?

So basically the title sounds way fancier than the actual question.

I am writing an application in which I开发者_如何学Go would like to implement an achievement system. If I have all of my achievements created as instances of a generic class, how do I write a method to validate those achievements (i.e. determine if the user has met or exceeded goals) when the type of feat accomplished may vary, the number of conditions to be met may vary and the type of validation may vary?

For example:

Achievement - 10,000 points!

Type - point total

Value (X) - 10,000

Conditions - 1

Validation - greater than X

vs.

Achievement - Ultra-frag

Type - kills

Value (X) - 10

Type - time

Value (Y) - 10 seconds

Conditions - 2

Validation - at least X in less than Y

I am trying to avoid hardcoding a validation function for every achievement since they are mainly generic and the only difference is how they are validated.

Like the achievement class looks something like

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

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

I am trying to think of a way to do this without function pointers and I am failing miserably. Also, can you even use function pointers in java? Im new to the language :(


I think the right track would be to have a validate method for each Achievement:

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

But that doesn't stop you from providing a few concrete implementations and configuring them with parameters.

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 Another option to prevent inheritance (and use composition) is to use is something similar to the strategy pattern.

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

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

When used with anonymous inner classes it's pretty much using function pointers

registerAchievement(new Achievement("Zombie Killer", new AchievementValidator() {
    public boolean isSatisfied(Data data) { return data.getZombieKills() >= 50; }
});


Function pointers in Java (and in general in any Object Oriented Language) are usually replaced by Polymorphic objects.

About not hardcoding the validation, I don't think it's worth to write a rule-engine for that, the effort would be much higher. What you can do is to unify the achievements of the same type as objects of the same class with a field having different thresholds values.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜