Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactors the code in the singlton design pattern

The original code was a little misleading and it also would compile with
a runtime error.

This offers a new version that illistrates the use of closures inside a
class definition. It also provides an example of how to handle modules
(including private classes) The two example together illistrate some of
the flexability and elegance CoffeeScript can offer. It also explains
how the use of the wrapper around a CS file.
  • Loading branch information...
commit 12d5623d7ebfa5b9875577a272ba372f1b906434 1 parent e73ee06
@sukima sukima authored
Showing with 56 additions and 40 deletions.
  1. +56 −40 chapters/design_patterns/singleton.md
View
96 chapters/design_patterns/singleton.md
@@ -7,59 +7,75 @@ chapter: Design Patterns
Many times you only want one, and only one, instance of a class. For example, you may only need one class that creates server resources and you want to ensure that the one object can control those resources. Beware, however, because the singleton pattern can be easily abused to mimic unwanted global variables.
+
## Solution
The publicly available class only contains the method to get the one true instance. The instance is kept within the closure of that public object and is always returned.
-The actual definition of the singleton class follows.
+This is works because CoffeeScript allows you to define executable statements inside a class definition. However, because most CoffeeScript compiles into a [IIFE][] wrapper you do not have to place the private class inside the class definition if this style suits you. The later might be useful when developing modular code such as found in [CommonJS][] (Node.js) or [Require.js][] (See the discussion for an example).
-Note that I am using the idiomatic module export feature to emphasize the publicly accessible portion of the module. Remember coffeescript wraps all files in a function block to protect the global namespace.
+[IIFE]: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
+[CommonJS]: http://www.commonjs.org/
+[Require.js]: http://requirejs.org/
{% highlight coffeescript %}
-root = exports ? this # http://stackoverflow.com/questions/4214731/coffeescript-global-variables
-
-# The publicly accessible Singleton fetcher
-class root.Singleton
- _instance = undefined # Must be declared here to force the closure on the class
- @get: (args) -> # Must be a static method
- _instance ?= new _Singleton args
-
-# The actual Singleton class
-class _Singleton
- constructor: (@args) ->
-
- echo: ->
- @args
-
-a = root.Singleton.get 'Hello A'
-a.echo()
-# => 'Hello A'
-
-b = root.Singleton.get 'Hello B'
-a.echo()
-# => 'Hello A'
+class Singleton
+ # You can add statements inside the class definition
+ # which helps establish private scope (due to closures)
+ # instance is defined as null to force correct scope
+ instance = null
+ # Create a private class that we can initialize however
+ # defined inside this scope to force the use of the
+ # singleton class.
+ class PrivateClass
+ constructor: (@message) ->
+ echo: -> @message
+ # This is a static method used to either retrieve the
+ # instance or create a new one.
+ @get: (message) ->
+ instance ?= new PrivateClass(message)
+
+a = Singleton.get "Hello A"
+a.echo() # => "Hello A"
+
+b = Singleton.get "Hello B"
+b.echo() # => "Hello A"
+
+Singleton.instance # => undefined
+a.instance # => undefined
+Singleton.PrivateClass # => undefined
+{% endhighlight %}
-b.echo()
-# => 'Hello A'
-root.Singleton._instance
-# => undefined
+## Discussion
-root.Singleton._instance = 'foo'
+See in the above example how all instances are outputting from the same instance of the Singleton class. You can also see that the PrivateClass and instance variable are not accessible outside the Singleton class. In essance the Singleton class provides a static method get which returns only one instance of PrivateClass and only one. It also hides the PrivateClass from the world so that you can not create your own.
-root.Singleton._instance
-# => 'foo'
+The idea of hiding or making private the inner workings is preference. Especially since by default CoffeeScript wraps the compiled code inside it's own IIFE (closure) allowing you to define classes without worry that it might be accessible from outside the file. In this example, note that I am using the idiomatic module export feature to emphasize the publicly accessible portion of the module. (See this discussion for further explanation on [exporting to the global namespace][1]).
-c = root.Singleton.get 'Hello C'
-c.foo()
-# => 'Hello A'
+[1]: http://stackoverflow.com/questions/4214731/coffeescript-global-variables
-a.foo()
-# => 'Hello A'
+{% highlight coffeescript %}
+root = exports ? this
+
+# Create a private class that we can initialize however
+# defined inside the wrapper scope.
+class ProtectedClass
+ constructor: (@message) ->
+ echo: -> @message
+
+class Singleton
+ # You can add statements inside the class definition
+ # which helps establish private scope (due to closures)
+ # instance is defined as null to force correct scope
+ instance = null
+ # This is a static method used to either retrieve the
+ # instance or create a new one.
+ @get: (message) ->
+ instance ?= new ProtectedClass(message)
+
+# Export Singleton as a module
+root.Singleton = Singleton
{% endhighlight %}
-## Discussion
-
-See in the above example how all instances are outputting from the same instance of the Singleton class.
-
Note how incredibly simple coffeescript makes this design pattern. For reference and discussion on nice javascript implementations, check out [Essential JavaScript Design Patterns For Beginners](http://addyosmani.com/resources/essentialjsdesignpatterns/book/).
Please sign in to comment.
Something went wrong with that request. Please try again.