I've found that in a lot of cases, it seems (at least superficially) to make sense to use Singletons or Static classes for models in my WPF-MVVM applications. Mostly, this is because most of my models need to be accessed throughout the application. Making my models static
makes for a simple way of satisfying this requirement.
And yet, I'm conflicted because everyone on the planet seems to hate singletons. So I'm wondering I there isn't a better way, or if I'm doing something obviously wrong?
The advantage of using a static class is the compiler makes sure that no instance methods are accidentally added. The compiler guarantees that instances of the class cannot be created. A singleton class has a private constructor that prevents the class from being instantiated. A singleton class can have instance members while a static class cannot.
Let us discuss more about the Singleton class first. Singleton is a design pattern that makes sure that your application creates only one instance of the class anytime. It is highly efficient and very graceful. Singletons have a static property that you must access to get the object reference.
Most of the time, if you're using static methods or variables then there is almost certainly a better way. That said, there are a few instances where static methods and variables are useful. However, all of these are accessed solely by methods in the class that also contains the statics, and do not have dependencies on anything outside them.
Because the Singleton instance is referenced by a private static member variable, the instantiation does not occur until the class is first referenced by a call to the Instance property. This solution therefore implements a form of the lazy instantiation property, as in the Design Patterns form of Singleton.
There are a couple of issues with Singletons. I'll outline them below, and then propose some alternative solutions. I am not a "Never use a singleton, or you're a crap coder" kind of guy as I believe they do have their uses. But those uses are rare.
Thread safety. If you have a global-static Singleton, then it has to be thread-safe because anything can access it at any time. This is additional overhead.
Unit Testing is more difficult with Singletons.
It's a cheap replacement for global variables (I mean, that's what a singleton is at the end of the day, although it may have methods and other fancy things).
See, it's not that Singleton's are "horrid abominations" per-se, but that it's the first design pattern many new programmers get to deal with and its' convenience obfuscates its' pitfalls (Just stick some gears on it and call it steam-punk).
In your case, you're referring to Models and these are always "instances" as they naturally reflect the data. Perhaps you are worried about the cost of obtaining these instances. Believe me, they should be negligible (down to data-access design, obviously).
So, alternatives? Pass the Model to the places that require it. This makes unit testing easier, and allows you to swap out the fundamentals of that model in a heart-beat. This also means you might want to have a look at interfaces - these denote a contract. You can then create concrete objects that implement these interfaces and voila - you're code is easily unit-testable, and modifiable.
In the singleton world, a single change to that singleton could fundamentally break everything in the code-base. Not a good thing.
I think the accepted solution to this problem is to use dependency injection. With dependency injection, you can define your models as regular, non-static classes and then have an inversion of control container "inject" an instance of your model when you want it.
There is a nice tutorial at wpftutorial.net that shows how to do dependency injection in WPF: http://wpftutorial.net/ReferenceArchitecture.html
The only static class I use is a MessageBroker because I need the same instance all through the application.
But even then it is very possible to use Unity (or another Dependency Injection/Container) to manage instances of classes that you only need one of.
This allows you to inject different versions when needed (e.g. during unit tests)
BTW: static is not the same as singleton. But I am not getting into that here. Just search stackoverflow for more fun questions on that :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With