4

So I have a player class in my game. Logically there only needs to be one player object (single player) But a lot of different classes need access to the player object. (ie, maps needs to know were player is, as does camera and enemies need to interact with the player, etc).

I have a couple of options.

Either I could pass this player object around to everything that needs it which is cumbersome. (Dependency injection I think it's called)

Just make it public static.

Make it a singleton.

What are the pros/cons of each?

user697111
  • 2,082
  • 7
  • 27
  • 39
  • 1
    See [this question](http://stackoverflow.com/questions/28241/java-singleton-vs-static-is-there-a-real-performance-benefit) for some possible guidance. – brc Oct 25 '11 at 03:46
  • 4
    Singleton is almost never the answer. What if you want to later make your game multiplayer? You've painted yourself into a corner. – Matt Ball Oct 25 '11 at 03:46
  • Have you considered [DI](http://stackoverflow.com/questions/130794/what-is-dependency-injection) so you don't have to pass it around all the time, but can route explicitly when you want to? – Mike Samuel Oct 25 '11 at 03:47
  • Can't wait to read all those "Singleton are evil" answers... – talnicolas Oct 25 '11 at 03:47
  • 2
    @MattBall, I don't quite agree with that. Singleton is after-all a factory and it can be easily enhanced to support an arg in `getIntance()` like player-id. – Kashyap Oct 25 '11 at 03:49
  • @Mike: Dependency injection **is** about "passing it around" (not all the time, but I think enough such that that's what our OP is trying to avoid). You pass it into anyone who needs it. The link you cite agrees with that (see the top answer). I think maybe you're thinking of a dependency injection *framework* to make it nicer to manage? – Mark Peters Oct 25 '11 at 03:49
  • Singletons are not evil. It just doesnt make any sense on this earth to say that. – DarthVader Oct 25 '11 at 03:50
  • 2
    you dont need DI for everything. not everyone uses DI for everything. it s not cool aid. – DarthVader Oct 25 '11 at 03:50
  • @DarthVader I suggested once to someone to use a Singleton (and it was a good use of it) and got downvoted because, as I've been told, "Singleton are evil". I agree it doesn't make sense. But heh, some people always know better apparently. – talnicolas Oct 25 '11 at 03:52
  • they are called Google fanboys! and they are not always right. – DarthVader Oct 25 '11 at 03:53
  • @brc: great link. This quote especially: "I would use a singleton if it needed to store any state, and static classes otherwise. There's no point in instantiating something, even a single instance, unless it needs to store something." – paulsm4 Oct 25 '11 at 03:54
  • 1
    @Darth: There are many valid justifications for not using singleton as much as there are valid justifications *for* using singleton. In my experience, applying singleton to more than an extremely narrow range of problems leads to hard-to-test and poorly designed code. That's not fanboyism, it's real-world experience. – Mark Peters Oct 25 '11 at 03:54
  • 3
    Singleton is the new black :) – Shahzeb Oct 25 '11 at 03:54
  • 1
    That s exactly what it is, TDD. that s why they dont like singletons as much as they dont like static classes.because they are harder test. But there is nothing wrong with them. I have seen rock star programmers use them without a doubt. they are just talking about a good approach. – DarthVader Oct 25 '11 at 03:56
  • @Mark Peters, I don't think we disagree. DI is about passing it around, but removes the burden of *explicitly* passing it around. Right? – Mike Samuel Oct 25 '11 at 16:00

6 Answers6

4

I would not use a Singleton or static variable here and instead would hand a Player instance to the classes that need it via setters. If you only need one player instance - only call new Player() once :-)

See my take on Singletons here. Short summary: their typical misuse (avoiding "cumbersome" setters) violates OO and lowers design quality.

Static variables are cut from the same cloth as Singletons, along with the Monostate (non-static getters, static data, constructor is the "factory"). Avoid them. Consider if you made everything static: player, map, camera, enemies, etc. You would avoid a lot of "cumbersome" setters. But is it OO? When you finish your game can you reuse your pathfinding algorithms, AI algorithms, etc. on another game, or do they have too many global variables (Singletons et al) specific to your current game burned into them forever?

Community
  • 1
  • 1
SingleShot
  • 17,762
  • 13
  • 66
  • 100
  • ok, so pass it around. What if ten classes need it though? I have a world that has a map array and that map array has tile arrays. Everyone of these will have to get the player passed to it. That is ok? The problem I see is that it works for the game, but won't work for my map editor. – user697111 Oct 25 '11 at 16:15
  • @user697111 Yeah, that's okay. I'd recommend using a dependency injection framework such as Guice: http://code.google.com/p/google-guice/ – PaoloVictor Oct 25 '11 at 16:34
  • @user697111. I agree with Paolo. "Wiring" classes together by passing one into a setter on another is the way to go. I favor using Spring to do the wiring, but as Paolo says, Guice is a choice, and if you aren't comfortable with either, just calling the setters from your `main()` or whatever works too. – SingleShot Oct 27 '11 at 02:23
  • Regarding your map editor - if it won't work because it shares the same code as the game but makes no sense to pass in a player object, then the design is not quite right. Try to separate out the code that cares about players from the code that does not. This may be an indicator that your map should not know about players - maybe it should be the other way around, or something else... – SingleShot Oct 27 '11 at 02:24
1

So, your options are:

Just make it public static. Make it a singleton.

Both would effectively turn it into a global variable. I'm not a big fan of globals: they make everything harder to test and debug.

Pros: Easier access

Cons: Very high coupling (what if you want to make it a two player game?); Adds complexity to tests; Changing the player in one place might have unexpected consequences on other places.

I could pass this player object around to everything that needs it which is cumbersome. (Dependency injection I think it's called)

Pros: Lower coupling; Facilitates testing; You can pass copies of the player to other classes and reduce the chances of side-effects.

Cons: Having to pass Player references makes the API a bit more complex, but part of it may be mitigated by using a dependency injection framework, such as Guice.

PaoloVictor
  • 1,246
  • 8
  • 18
0

Apart from teh advantages provided by Java Setter and Getter, I can't really think of any new ones that a singleton pattern (public static Type getInstance()) would give you over public variable (public static Type var).

But in general it's always better (from future pov) to control access to member variables (especially access from outside the class that has this as member variable), so I would recommend a private static variable with a public getter. Which is somewhere between a singleton and a public static var.

Community
  • 1
  • 1
Kashyap
  • 12,510
  • 8
  • 55
  • 90
0

Using a singleton gives you the possibility to extend the base class and provide alternative implementations of Player, using a static method does now allow that flexibility.

Another point is that "conceptually" a player is an object and not a class.

RAY
  • 6,104
  • 5
  • 35
  • 65
  • Actually, a traditional Singleton cannot be extended. – SingleShot Oct 25 '11 at 05:37
  • Don't think you get what I mean. Say Player is an abstract class, then you can a Player singleton at run. You may use a simple config change before you launch your program to decide the actual concrete class of Player you want to instantiate as your singleton. – RAY Oct 25 '11 at 06:49
0

I would avoid making it static. You want your code to be reusable and a player is certainly an object that may require several instances in an alternate project.

I would create simple getAttribute(), editAttribute methods that return or edit the attribute I need.

Another option would be to simply make the shareable attributes public within the player class although I would prefer the get/edit methods option.

Declan McKenna
  • 3,803
  • 6
  • 39
  • 67
0

Singletons can implement interfaces which can be used to refere to the singleton. i.e. you don't need hardcoded references to a singleton throughout your code. This makes unit testing easier, if you want a different instance for testing purposes.

public interface Printer {
   public void print(String line);
}

public enum ConsolePrinter implements Printer {
   INSTANCE;
   public void print(String line) {
       System.out.println(line);
   }
}

// to print to the screen
Printer printer = ConsolePrinter.INSTANCE;

// for testing purposes.
Printer printer = createMock(Printer.class);
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075