- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
I like this new trend of Remy's comments in CodeSOD articles.
Admin
Thanks for those insights!
The reason I use a Singleton in this case is actually not as a worker, but as a persistent cache of settings.
Yes, I know it's akin to the idea of Global variables in an Object-Oriented program, which is a WTF in its own right, but given that I have to store and load this information from save files, as well as make it persist across scenes/application states, I am finding it simplest and most maintainable to do it this way in this instance.
My actual control is happening via other objects - the Maestro object I mention in my blog post monitors those Settings and knows how to interpret a PlaySoundEffect instruction, or tell the AudioSource (a Unity object) how to change background music. Settings GUI performs the value-set operations, obviously, as will Game Load system when that is implemented.
As a rule in my own development, I only use a singleton when an object fulfills the requirement that under any circumstances, one and only one of it should exist at any given time. It's an easy pattern to abuse, as you (and others) have shown.
Admin
You mean it's almost like it is a Repository of settings?
How do you test your code that uses that object in a manner that isolates that object?
I don't think adding eventing to your system is at all too big of a deal: unless you throw away your game engine every time, in which case there's plenty of other WTFs in what you're doing and you have yourself a big ol' WTF onion.
If you don't have eventing and a clear separation of concerns, then you likely have a deep, or going to be deep, object hierarchy too... a Player might be a Character and a Monster is also a Character and yadda yadda yadda.
Eventing and data-driven go well together and will let you have testable, resuable, separate and maintanable code.
You can also use DI without the framework, in which case, yes, your AudioEventHandler should get an instance of the SoundManager provide to it - when you use Singleton, you're explicitly coupling that SoundManager implementation to it's use. You're doing the same thing, you just for some reason think it's more readable to have the dependency implicitly wired all over the place, rather that explicitly in the constructor.
Also, by wanting "one instance" of something, you basically set yourself up for issues with multi-threading (not so bad) and multi-process (a complete fucking disaster). Maybe not relevant to a tiny game, but in a web application, youre almost guaranteed to be multi-process at any scale except prototyping.
Admin
Or if you're using a DI engine, who decides how many DI engines there are?
I'm working on a code-base that had a large number of singletons. In adapting it over the years, we've made significant changes to what goes on under the hood. A call to Logger.getInstance() no longer returns a static instance member, it forwards the call to a single instance of a SingletonManager class, which returns the appropriate instance of a Logger. In essence, we now only have a single singleton, the SingletonManager. Except that it doesn't actually construct itself, it relies on SingletonManagerStore - which is an abstract class with different implementations for different environments. One that stores the SingletonManager in memory, for normal executables, one that stores it and retrieves it from HttpContext.Current.Session, when used in ASP.NET, etc.
Underneath, you could argue that this isn't actually singleton, anymore. But for the coder who's calling Logger.getInstance(), it looks like it's a singleton.
Admin
Admin
Admin
The user? By virtue of how many instances of the application they start?
Why not LoggerFactory instead of a (presumably) multi-use SingletonManager?
Admin
-Harrow.
Admin
That's a much more concise way of putting it...really, it is a Repository. Its only concern is the storage and persistence of data. Other things, such as the Settings GUI and Maestro, consume this data.
I actually don't have to worry about throwing things away too much, given the way Unity is set up. Also, eventing is a core concern of Unity; it provides a rather nice event system that I take advantage of in a number of ways, including the application of the saved settings.
While I agree a deep hierarchy should be carefully considered, having a hierarchy is not necessarily a problem.
The case you gave, while I use different terms in the code I've developed, is an apt one. An entity that can be engaged in a battle is...well, an Entity (has a health system and combat rolls, pretty much). In a standard JRPG there are two types of combative entities - players, and enemies.
What is the difference between enemies and players? Players equip Equipment and Aethos (the customization system of the game...just nod and continue...), while Enemies drop various things, like Consumables and Equipment.
On that note, Equipment, Aethos, and Consumables are all RPG Items. The abstract RPG Item defines a basic contract among items; the derived item classes state the applicable differences (e.g., you cannot Equip a Tonic, but you can drink it to restore 150 HP. Your Equipment confers stat bonuses, but Aethos also confer skills and stat bonuses, and further can level up to a certain point).
First paragraph - I have no contest to this point. This is the downside of using a Singleton, and why I considered everything I know of before deciding to use a Singleton (which, is admittedly not much).
Second paragraph - while this is not an issue for me at present (Unity handles multithreading behind the scenes for me), if I were to make my own custom game engine, you'd be right beyond a ghost of a doubt - I would almost certainly have to multithread or multiprocess to achieve playable performance.
Admin
Shouldn't that be throw an exception in this case? :-)
Admin
Right, which is why it might serve you well not to use a Singleton for it. You may test with an InMemorySettingsRepository or a MockSettingsRepository (or Fake, or whatever) - you may use a ProprietarySettingsRepository that uses a file format you create, or an XmlSettingsRepository. Or a CloudSettingsRepository.. just saying, you may need one or more of those a any point. I don't see how Singleton helps you here.
Sure, but if that's all you're using it for I think you're selling yourself short.
Well, I am not a professional game developer, but I have seen some interesting material about how absolutely insanely large commercial games can get when the use inheritance to model game logic/rules/concepts. Inheritance is an is-a approach, and while it's really easy to agree that Equipment is an Item, and so is a Consumable, it's not always going to be that simple. What about Equipment that can only be used once? Is that a Consumable? Or does Consumable imply that the player actually eats it? What then is the property that actually causes those objects to diminsh? Do you call them Finite? Is a Sword a piece of Equipment that implements Repairable, Damaging and so on? It seems appealing to try to categorize things that way, but I think it's a lot easier to manage when instead you think that a Sword is an Item with a Set<Attribute>. You can then have CompositeAttribute use the Specification pattern to define valid/invalid Attribute definitions (for example, Indestructable can not be Repairable) - this is harder to do with interface/multi-inheritance. You can also externalize those definitions which makes your game-engine really reusable because you don't have a compile-time definition of what is/isn't possible.
Admin
The code used to get the instance isn't shown, but I assume it would typically be something like this:
After all, if one Lone Ranger is good, a legion of them would be better, right?
Admin
HAHAHAHAHA! (More non-spam text?_
Admin
I think there's a missing step in this (no pun intended) logic.
As stated, the best I can make of this argument is, "This thing is easy to use and is very useful, therefore you shouldn't use it."
Like, "You shouldn't do addition in your programs. The plus operator is very easy to use and does addition easiy, so your'e tempted to use it to much."
Admin
Well, if you have a clustered app, then you can't implement a singleton with the simple "private static MySingleton instance" approach. You need to store the singleton somewhere that will be "single" for the whole app, not just "single" to one node on the cluster. I suppose you could say that singletons don't scale, that is, if you have an app that was written for a single server, and that app uses singletons, you can't necessarily just drop it into a clustered-server environment. You'd have to look at how the singletons were implemented and probably redesign them. I'll agree that that's an argument against singletons as currently implemented given today's state of the art. But one could argue that that's a deficiency in current language implementations rather than in the concept of a singleton. The same objection would apply to all static data (shared data for you VB folks).
Admin
The getInstance method should instantiate the instance variable using the constructor, which should be private. No?
Admin
GoF included things like Vistors and Decorators and Delegates specifically because is-a relationships can get very complex and multiple inheritance is a potential nightmare.
As a general rule, any hierarchy deeper than three levels needs to be justified. This goes for inheritance trees, file organization schemes, and slide presentations.
Admin
The operative word is that it seems useful, not that it is useful. Global variables also seem useful, and they are really easy to implement- at least until you have to support them. Then you discover how much spaghetti they actually create.
Admin
Hmm, interesting, but I don't see how this would be superior to implementing a SoundManager singleton.
I don't know exactly how the original poster implemented this, but logically you could create a "playSound" function that takes an argument that describes what sound. Like "SoundManager.getInstance().playSound(FIRE_PHASORS)". The spaceship class then doesn't know anything about how to play sounds. It just knows to call the sound manager to do it. If you decide to change the sound the spaceship makes, you change the code in playSound, not in the spaceship class. Responsibility is properly delegated.
To accomplish what you're describing, every class that is associated with a sound would have to provide a hook to declare a listener. Then it would have to call the listener when it was time to play the sound. So instead of a single playSound call, we now have to define a listener field, create an addSoundListener function, and then we still have to call soundListener.playSound. Then we have to write code in another class that registers the sound listener with the spaceship object. Instead of one line of code, we have 10 or 20 lines of code to accomplish the same thing, split across at least two classes and four or more functions.
And what have we gained? It gives us the ability to have multiple, different sound managers, so we can register different sound managers with different "sound-producing" objects. Maybe there's value in that, but I doubt it. If different sounds are produced in different ways -- like some are produced by playing an AVI file while others are synthesized internally with code -- we could handle the distinction in the sound manager based on the sound identifier passed in. This would probably be easier than having multiple sound managers registering themselves.
If you are creating a game engine API where the sound manager is not part of your API, an observer pattern might be a good idea as it lets the caller supply its own sound manager. That's about the only case I can think of where it would offer an advantage.
Admin
Why does the spaceship know about sound at all?
those sounds emit in response to events generated by the spaceship.
i'd want my spaceship to fire a weapon, and that to produce a weapon_fire event, which the sound system observes and produces based on the type of the weapon. that way, if a turrent also has a weapon which can fire, it's all done. I don't have to worry about forgetting to make the turrent play a sound when it shoots.
Admin
Admin
The starship class needs to know that PHASORS make sounds. Why? What happens when we change our business rules and decide that PHASORS only make sounds in certain conditions. Do we put that logic in the SoundManager or the starship class?
As I stated in a different comment, a better approach would be to let the GameEngine manage this. In each tick of the game, the GameEngine passes the relevant portions of the object graph off to the SoundManager and the Renderer objects. The observer pattern is, admittedly, overkill, but the Singleton pattern is hiding simplicity in global variables, which means lots of spaghetti code.
The starship object should be focused on the business rules of starships. How to move. How to shoot. How to update stats as it takes damage and consumes inventory. Other objects should be responsible for deciding that sounds need to be played.
I wrote a Singleton last week. I have a a set of Handler classes. I have a service that receives requests. Each request can be handled by a different type of Handler. I wrote a Singleton to use as a Factory; it uses reflection to find all concrete classes that implement the Handler interface and creates instances of them. When a request comes it, it invokes the CanHandle method on each Handler to find the Handler that's suitable for that request.
I chose to make that factory a Singleton because a) I don't want to reflect the assemblies for each request, and b) it's possible that the instantiation of a Handler might be expensive.
Now, only one class ever actually creates an instance of the Factory, and the beauty of that is that it allows me to restrict object creation. My Singleton is not, and could not be used, as a global variable. The internal/package/friend access modifier exists for a reason.
As a side effect of this design, the individual Handlers are singleton by convention. I never create more than one instance, but I could if I ever wanted to. The Handlers are completely reusable. They're also stateless-by-convention, and there's a rule I wish I did have: "This class and all its children are stateless, and may not implement any data members."
Admin
That code is not OK. Should have been somrthing like this
public static KpiService getInstance(){ return instance ?? instance = new KpiService(); }
private KpiService(){ }
Notice the constructor is private (This way, u can't just create a new KpiService. You have to go through getInstance() to get the singleton object
Admin
That code is not OK. Should have been something like this
public static KpiService getInstance(){ return instance ?? (instance = new KpiService()); }
private KpiService(){ }
Notice the constructor is private (This way, u can't just create a new KpiService. You have to go through getInstance() to get the singleton object
Admin
When global variables are used to pass parameters between functions, they are horriby evil. I absolutely agree with that. But that doesn't mean that global data is always evil. Some data is rightly global.
I used to work at a company where the programmers were always looking for new ways to create global data. They would put EVERYTHING in session variables. Then we'd have all this dangling junk data sitting in the session. When someone came back to modify the program, it was almost impossible to figure out who put the data there or what it was for. The connections between modules were lost. When we beat that out of them, they started putting function parameters in static fields. After a few more beatings, they had to find other tricky places to hide it. For some reason people just couldn't get the idea to pass parameters between functions as, say, function parameters. I went crazy at that place.
But that doesn't mean that global data is never appropriate. It makes good sense for data that legitimately applies all over the place and which there should be only one copy of. Like, what's the user's timezone? Many modules might use that. Rather than pass it in and out of 1000 places, it makes sense to keep it in a global somewhere. Or user preferences. Yes, we could load preferences in a start-up function and then pass them to everything, but it's a pain and it gains nothing.
What's the difference? When data applies to the application as a whole, it's legimately global. When it applies to one particular thing we're doing right now, it is not legimately global. What is the current user's name? Fair game for global. What is the name of the customer on the transaction we are currently processing? Not fair game for global at all.
Admin
I'm not saying "Never use singletons" or "never use globals". But they should be used sparingly. And for the most part, singletons should be implemented by convention, not by pattern.
Globals for things that are truly global, singletons for things that are truly singular.
Admin
I'd put that logic in the PhaserEventHandler which listens for PhaserFireEvent and then, based on the attributes of the Phaser that is being fired, play a sound. Just like, if instead it were a SniperRifle and it had a Silenced attribute, the handler would play a different sound.
The idea that the Player knows that their SniperRifle makes a sound isn't very useful, and it means that they need to know about the assets involved (either directly as resources, or indirectly as method calls: playSilencedSniperRifleSound()).
When I shoot a gun, the air around me makes the sound, not me.
Why? This is dogma. The starship is just a set of data: it is the union of a Thruster, a Hull, a Shield and a Weapon.
When the player presses X, the Thruster emits an event indicating that it is active. The game engine delegates that event through handlers which then apply forces to the various entities that represent the physical model of the ship. The rendering subsystem updates the view of the ships physical model based on the observation of its physical state. Does the Ship need to know how it collides with other ships now, too? There's virtually no limit here.
I wouldn't even have a Ship class. It's just a definition of a set of attributes that themselves may be composed of other primitive attributes in a very shallow hierarchy.
You used a Singleton to facilitate Chain of Responsibility. I don't see how the former is needed for the later.
Then your concerns about performance were a little unnecessary and your design decision seems tantamount to premature optimization.
You mean immutability?
Admin
Hey, you know what would be a good pattern to enforce that there is only one instance of this SoundManager class? lol
I too don't get the singleton hate. I agree that if you have more than what you can count on one hand in any given application you probably are over-using them, but I will use them any time there should only ever be one instance of a class. I have made a SoundManager singleton for some apps. And in a couple lightweight MVC frameworks I've developed, the controller class is a singleton.
Admin
If a Thruster is a meaningful object in your context, fine. But we're getting too bogged down in the details of a hypothetical application and losing track of the core premise: objects should be focused on doing the job of being themselves. If we're building a Galaga clone, you've just terribly over-designed the application.
Only one class actually creates an instance of the Factory. I didn't mention how many instances of the client class there were. There will be a large number of clients accessing the Factory.
Immutability and statelessness are not the same, but I'd be fine with immutability as well. There are OO languages that have things like that, and there are plenty of functional languages that do.
Admin
Just to expand on this:
If the person firing the Weapon is the one who has to play the sound, they they must also become aware of all the rules that could alter how the sound is played. This is a clear violation of SRP.
This means that if the Ship can fly in to the atmopshere as well as out in space, and you want to accurately model the fact that sound doesn't travel in space (nevermind why: that's irrelevant) - then suddenly your ship has to be able to tell if it is in space or not. I'm not talking about a HUD saying "You're now in space d00d!!!1elevent" - I'm talking about, at a code level, the spaceship now needs to be able to perform a test, or acquire information from somewhere ... and guess what? That leads to SomeSingleton.getInstance().isInSpace(this) or just a static method call. And if you want to add this feature, you have to go through and do it everywhere that plays sound. This is not DRY at all.
Whereas, in the WeaponEventHandler (I wouldn't even have Phaser as a class/event handler), I could add that check, and it might not be very pretty, but at least it is in one place. It's no less pretty than putting it in the class 'using' the Weapon, but it's a lot more maintainable/testable.
Then again, you could set up a Chain of Responsibility in the WeaponEventHandler at that point, refactor the old one to be a TerrestrialWeaponEventHandler and a SpaceWeaponEventHandler and so on and so forth.
Admin
The constructor is public, allowing anyone to create a new singleton whenever.
Nowhere in the cited code is that construction initiated; if the "SNIP" section only contains functional bits of the singleton, the singleton is relying on something external to initialize it by constructing only one of these.
One can easily find the Right Way to do this by doing a bit of Googling,or alternatively by using a framework like Spring that provides baked-in singleton initialization.
Admin
[quote user="Dave Insurgent"][quote]That's a much more concise way of putting it...really, it is a Repository. Its only concern is the storage and persistence of data.[/quote]
Right, which is why it might serve you well not to use a Singleton for it. You may test with an InMemorySettingsRepository or a MockSettingsRepository (or Fake, or whatever) - you may use a ProprietarySettingsRepository that uses a file format you create, or an XmlSettingsRepository. Or a CloudSettingsRepository.. just saying, you may need one or more of those a any point. I don't see how Singleton helps you here.[/quote]
You have a point here. Depending on one's opinions on the Singleton, a singleton just does the same thing with a different flavor.
If you look at my webplayer, there are three actions the user can take on the title: Settings, New Game, and Load Game. Settings serves to set the settings up from the title screen, such that when a new game is started, the user already has their settings set up. The Load Game option is just going to overwrite that when it loads from the save file.
The point I think I see from your argument is, instead of using a singleton, just create class(es) that live in the background (like the singleton currently does), and serve up information as it is needed (e.g. sound settings repo, graphics settings repo, etc.) It's easier to test by using unit tests, etc.
I have to admit - I berate myself for not thinking of the problem in that way. Lack of experience on my part; I'll give that setup a shot!
[quote]I actually don't have to worry about throwing things away too much, given the way Unity is set up. Also, eventing is a core concern of Unity; it provides a rather nice event system that I take advantage of in a number of ways, including the application of the saved settings.[/quote]
Sure, but if that's all you're using it for I think you're selling yourself short.[/quote]
I'm a bit confused by this statement. What other possibilities do you see?
[quote]While I agree a deep hierarchy should be carefully considered, having a hierarchy is not necessarily a problem.[/quote]
Well, I am not a professional game developer, but I have seen some interesting material about how absolutely insanely large commercial games can get when the use inheritance to model game logic/rules/concepts. Inheritance is an is-a approach, and while it's really easy to agree that Equipment is an Item, and so is a Consumable, it's not always going to be that simple. What about Equipment that can only be used once? Is that a Consumable? Or does Consumable imply that the player actually eats it? What then is the property that actually causes those objects to diminsh? Do you call them Finite? Is a Sword a piece of Equipment that implements Repairable, Damaging and so on? It seems appealing to try to categorize things that way, but I think it's a lot easier to manage when instead you think that a Sword is an Item with a Set<Attribute>. You can then have CompositeAttribute use the Specification pattern to define valid/invalid Attribute definitions (for example, Indestructable can not be Repairable) - this is harder to do with interface/multi-inheritance. You can also externalize those definitions which makes your game-engine really reusable because you don't have a compile-time definition of what is/isn't possible.[/quote]
I love this bit here. I am going to write a blog article on it. I did some really good thinking over lunch on it.
To answer some of the questions, I can invoke "A wizard did it." By that, I mean, in my specification of the system, I've already defined business rules like, "Equipment and Aethos cannot be Consumables." (Though that would be interesting; imagine whacking an enemy with a gummy sword, then eating part of it to restore HP! I'm thinking about that one too, btw!)
That being said, I also see YOUR way of things - what if, in a future project, I want items to be degradable? What if I want to implement the Gummi Sword? The way you defined would be better.
So, well-stated...I've got much more to consider going forward. And that's a good thing; player stats were what I was looking at working with next...
Admin
I disagree. I'm advocating for a data-driven model, which is philosophically different than your object-orieted model, and I'm trying to demonstrate why games specifically seem to be a good candidate for it.
I too like rich domain objects, but what are those domain objects? I'm proposing that in a robust game engine that is easy to work with and appropriate for multiple purposes, the domain is a much smaller set of data than the higher order combinations you're operating with.
Oh, I agree - but they both exist in a way that produces no side effect on themselves. Can you think of a time when using one would be appropriate, but not the other? (Performance or memory aside, I mean, from a correctness perspective).
Admin
There's lots of things wrong with this.
KpiService.getInstance().foo() - never calls constructor.
KpiService junk = new KpiService(); KpiService.getInstance().foo();
It would be possible to change the instance variable by creating another KpiService object, thus violating the whole singleton concept.
Admin
I'd like to read it - feel free to send an e-mail to doug dot moscrop at gmail dot com - if you're so inclined - when you post it.
Admin
Not to mention you can also write automated acceptance tests for them, so that your game, as an application of your game engine, is driven not by the "wizard specification" (nicely put), but by an actual spec - that maybe someone else a little more 'product-oriented' or 'business-oriented' (almost like an analyst... for business!) writes themselves.
Admin
For example, if your game objects themselves detect collisions, then which is correct? player.checkCollision(enemy) or enemy.checkCollision(player) or both? What about collisionManager.check(player, enemy)?
Singletons can get the job done, but it's not ideal. They allow you to be lazy and not think things through. This results in terrible design decisions that don't actually make any sense at all, but are allowed to happen because of the global state. Most importantly, just because you only need one of something doesn't mean that you have to assert that only one of something can ever exist. That's just dumb. It prevents object-oriented programming from being used as intended.
Watch this if you haven't yet and be enlightened:
http://youtu.be/-FRm3VPhseI
Admin
TDD in a nutshell...I've been exposed to it, and trying to integrate it into my very-indie dev ops at home.
Well, we should thank the TDWTF staff - the WTF posted has helped one developer see another set of WTFs in his own work! Thanks Remy et al!
Admin
In any case... what does this have to do with the whether to use singletons or not? Even in the case where Spaceship calls SoundManager:getInstance(), if what is returned is a singleton or not should be of no concern to Spaceship. It's purely an implementation detail of SoundManager.
Admin
@Remy - Question.
Reading the replies in between my exchange with Anonymous Dave, I notice he's not the only one who considers the Singleton as something that, while it appears helpful, is only half as helpful as the next best solution.
You mentioned you're using a singleton in an app you're using. I would assume you're using it the "right" way (after all, you're an editor for TDWTF, not a regular submitter)...what/when is the right way/time to use a Singleton class?
Admin
One problem is that getInstance() will be called before the constructor unless the programmer explicitly "news" the object first. And why is the constructor public. Yeah, this is a WTF.
Admin
You sound like the love child of Nagesh and Immanuel Kant.
Admin
If you want to get rid of that too, assign a newly created Singleton object to _Instance in it's declaration - such static variable initializers are guaranteed to run once and only once when the class is first loaded.
Admin
Is that the is that Clinton referred to? Is that the is that is? Or aren't?
What the hell is a singleton? Something to do with a card game the last I knew. Why are we talking about a card game on TDWTF?
Admin
We've had them since the dawn of time - they're called globals.
Admin
FWIW - I think configuration and some type of loggigns are two good examples where global stuff makes some sense - But in both of these instance is because the data is basically constant - and certainly pertinants to almosts all of the app. Loggings is a little more difficults because we may want to separate out multiple types of loggings....but assuming their is one globals error log it would makes much sense to alway be loggings through the same instance.
But maybe not too...
Admin
You have a point here. Depending on one's opinions on the Singleton, a singleton just does the same thing with a different flavor.
If you look at my webplayer, there are three actions the user can take on the title: Settings, New Game, and Load Game. Settings serves to set the settings up from the title screen, such that when a new game is started, the user already has their settings set up. The Load Game option is just going to overwrite that when it loads from the save file.
The point I think I see from your argument is, instead of using a singleton, just create class(es) that live in the background (like the singleton currently does), and serve up information as it is needed (e.g. sound settings repo, graphics settings repo, etc.) It's easier to test by using unit tests, etc.
I have to admit - I berate myself for not thinking of the problem in that way. Lack of experience on my part; I'll give that setup a shot!
I'm a bit confused by this statement. What other possibilities do you see?
I love this bit here. I am going to write a blog article on it. I did some really good thinking over lunch on it.
To answer some of the questions, I can invoke "A wizard did it." By that, I mean, in my specification of the system, I've already defined business rules like, "Equipment and Aethos cannot be Consumables." (Though that would be interesting; imagine whacking an enemy with a gummy sword, then eating part of it to restore HP! I'm thinking about that one too, btw!)
That being said, I also see YOUR way of things - what if, in a future project, I want items to be degradable? What if I want to implement the Gummi Sword? The way you defined would be better.
So, well-stated...I've got much more to consider going forward. And that's a good thing; player stats were what I was looking at working with next...
Admin
Singleton method is usually just a way for people to have globals without having globals. Singleton is the diet soda of design patterns.
Singleton makes a little sense if it's life-threateningly mission critical that there only be one instance. Otherwise you're just using your class itself as a container for a global variable, rather than storing the instance somewhere that actually makes sense.
Admin
I won't claim that I made a perfect implementation of singletons, but I can at least promise that I thought about it before I did it.
My pattern, as mentioned, was a Factory sitting atop a Chain of Responsibility. Creating the chain is potentially expensive- in this case, some objects might need to talk to the filesystem, a database, or some other resource-heavy store. Once the chain is created, however, each object doesn't expect it to change. Each object in the chain is stateless, or at least should be. Essentially I have a set of incoming requests, each request should be handled by an instance of the appropriate handler for that particular request.
My reason for using a Singleton wasn't quite my own personal dogma: a singleton should wrap objects that are truly singular.
Instead, I decided that an object should be singular because a) the objects it managed were stateless, b) creating those objects could be expensive, and c) I could control who accessed the singleton instantiator.
And before you get too excited about TDWTF editors being magical fonts of programming wisdom, I have personally written up a few of my own WTFs as articles. In fact, I will give out some spoilers: I was the mentor in my next WTF, and was at least partially the source of the WTF. There are reasons I didn't route around it, but mostly it boiled down to a "Not my problem" situation.
Admin
Sure, I'm not sure why that matters. Arguably, if you're using Singleton, I'd really expect them to be stateful, because that's what you wanted to do: capture universal state. Otherwise it would just be static method calls.
I guess the alternative is that they're not stateful, but they do have some creation-time configuration.
In the former case, using Singleton still presents the ususal problems of testability and you could still just use dependency injection to pass one instance around right from main.
In the later, I don't see any reason to enforce the one-instance rule because either your performance concern is premature/inappropriate (if you follow the same dependency injection adherence as above) or a case for a Flyweight - which is to say, I'd like to have one instance, but is it incorrect to have more than one? How can that be, if they're stateless?
I guess you could argue that they might end up configured differently..