Have you ever wanted to create a class that can only have one instance?
Yes? No? Maybe?
Well…
That’s exactly what the singleton pattern is.
There isn’t a problem with that.
But some people call this an anti-pattern because it can be used as an excuse for bad design.
Let’s have a look at a code example so you can learn how it works.
Singleton Pattern Code Example
The idea of the singleton pattern is that you want a class with only one instance.
Here’s how:
- You make the
new
method private - You define a class method named
instance
that returns the unique instance for the class
Because this is a popular design pattern, the Ruby standard library comes with a Singleton
module you can include in any class.
It looks like this:
require 'singleton' class Shop include Singleton end
Now if you try to create a Shop
object with Shop.new
you’ll see this:
Shop.new # NoMethodError: private method `new' called for Shop:Class
And if you want to get the one & only Shop
object you can use the instance
method:
Shop.instance.object_id # 5659218 Shop.instance.object_id # 5659218
You can tell it’s always the same object because the object_id
never changes.
What you need to remember:
This is a simple pattern, it limits object creation to 1 object & you can request that object whenever you want.
Why You Shouldn’t Use This Pattern
The singleton pattern is often an excuse to have some form of global variable & we know global variables are bad because you have no control over them. This makes things harder to test & it can increase coupling.
“The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object.” – Kent Beck
Imagine having an object that most of your classes depend on, that’s what the singleton pattern can become. Good luck refactoring that!
Now:
Are there any good uses for this pattern?
Searching on Github turned up some repos using the Singleton pattern in conjunction with the Null object pattern.
I guess that makes sense, Rails uses this as part of ActionPack.
Here’s the code:
class AllType < Type include Singleton def initialize super "*/*", :all end def all?; true; end def html?; true; end end
This is a class that inherits from Type
.
When you create an AllType
object via the instance
method, it will call super & return the object.
Every time you call instance
after that you'll get the same object.
In conclusion:
Yes, this pattern can be useful in the right situations, but you don't want to use it without thinking a lot about it.
Video
[responsive_video type='youtube' hide_related='0' hide_logo='0' hide_controls='0' hide_title='0' hide_fullscreen='0' autoplay='0']https://www.youtube.com/watch?v=QDqWQrK_FOg[/responsive_video]
Summary
You learned about the singleton design pattern, how to implement it in Ruby & why you should avoid it most of the time.
What do you think about this pattern? Have you seen it before? Let me know in the comments 🙂
Thanks for reading!