Have you ever wanted to create a class that can only have one instance?
Yes? No? Maybe?
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.
The idea of the singleton pattern is that you want a class with only one instance.
instancethat 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
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.
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!
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
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.
Yes, this pattern can be useful in the right situations, but you don't want to use it without thinking a lot about it.
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!