user1066015
user1066015

Reputation: 21

Looking for an appropriate design pattern

I have a game that tracks user stats after every match, such as how far they travelled, how many times they attacked, how far they fell, etc, and my current implementations looks somewhat as follows (simplified version):

Class Player{
    int id;

public Player(){
    int id = Math.random()*100000;
    PlayerData.players.put(id,new PlayerData());
}

public void jump(){
    //Logic to make the user jump
    //...

    //call the playerManager
    PlayerManager.jump(this);
}

public void attack(Player target){
   //logic to attack the player
   //...

   //call the player manager
   PlayerManager.attack(this,target);
}

}

Class PlayerData{
    public static HashMap<int, PlayerData> players = new HashMap<int,PlayerData>();
    int id;
    int timesJumped;
    int timesAttacked;

}
public void incrementJumped(){
    timesJumped++;
}
public void incrementAttacked(){
    timesAttacked++;
}

}

Class PlayerManager{

public static void jump(Player player){
    players.get(player.getId()).incrementJumped();
}
public void incrementAttacked(Player player, Player target){
    players.get(player.getId()).incrementAttacked();
}

}

So I have a PlayerData class which holds all of the statistics, and brings it out of the player class because it isn't part of the player logic. Then I have PlayerManager, which would be on the server, and that controls the interactions between players (a lot of the logic that does that is excluded so I could keep this simple). I put the calls to the PlayerData class in the Manager class because sometimes you have to do certain checks between players, for instance if the attack actually hits, then you increment "attackHits".

The main problem (in my opinion, correct me if I'm wrong) is that this is not very extensible. I will have to touch the PlayerData class if I want to keep track of a new stat, by adding methods and fields, and then I have to potentially add more methods to my PlayerManager, so it isn't very modulized.

If there is an improvement to this that you would recommend, I would be very appreciative. Thanks.

Upvotes: 2

Views: 335

Answers (2)

Sachin
Sachin

Reputation: 18777

I am not at all an expert in design patterns. But this is what I think might be useful:

To add actions to the player, you might wanna look at the Strategy Pattern. Just google for it and you will get lot of examples.

Here is an attempt by me: enter image description here

For updating the player stats, I guess Observer Pattern will be helpful.

The Observer Pattern defines one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

It enforces loose coupling so that future changes are easy.

(You will have to read about Observer Pattern and also will have to see some examples. It is not as straight forward as Strategy.)

Upvotes: 4

avh4
avh4

Reputation: 2655

Due to the fact that you said you want to be able to add new stats and actions later, I would tend to make a stats object that doesn't need to know anything about the game it's recording. The advantage is that the Stats class would never need to change as you added new features.

public interface Stats {
  void incrementStat(Object subject, String stat);
  int getStat(Object subject, String stat);
}

You Player implementation would look something like:

public void jump() {
  // Logic to make the player jump...

  stats.incrementStat(this, "jump");
}

Of course, what you're trading for that flexibility is static type-checking on those increment methods. But in cases like this I tend to think the simplicity is worth it. In addition to removing tons of boiler plate from the PlayerData and PlayerManager classes, you also end up with a reusable component, and you can get rid of the cyclic dependency between PlayerManager and Player.

Upvotes: 0

Related Questions