CSC/ECE 517 Fall 2007/wiki1b 6 c1
Singleton Pattern
The Singleton pattern is a design pattern used to insure the existence of a single instance of a class in the run time. It constructs the object once and returns a reference to this object every time thereafter. In a multithreading environment, special care should be taken, as it will be illustrated later in this page.
Implementation
The Singleton pattern is implemented by
- Create a class with a method which will create a new instance of the class (If one doesn't already exist)
- The constructor of this class is turned to private or protected
- Another public function is used to call this constructor.
- If the object is not initialized yet (object == null) it calls the constructor and returns a reference else it will just return a reference.
In multithreading environment, a synchronized command should be used so not every thread in the program can initialize its own instance of the singleton class.
Example Implementations
To demonstrate further let us consider programs that implement a logger in Java and then in Ruby.
Java
public class LoggerSingleton { private static LoggerSingleton instance = null; private LoggerSingleton() { // Exists only to defeat instantiation. } public static LoggerSingleton getInstance() { if(instance == null) { instance = new LoggerSingleton(); } return instance; } // add other attributes }
Ruby
require 'singleton' class LoggerSingleton include Singleton end
Test singletons
Following a code to test singleton class in Java:
import junit.framework.Assert; import junit.framework.TestCase; public class TestSingleton extends TestCase { private LoggerSingleton logger1 = null, logger2 = null; public TestSingleton(String name) { super(name); } public void setUp() { logger1 = LoggerSingleton.getInstance(); logger2 = LoggerSingleton.getInstance(); } public void testUnique() { System.out.println(logger1); System.out.println(logger2); Assert.assertEquals(true, logger1 == logger2); } }
in ruby;
def test_singleton class << OnlyOne.instance def reset # reset state end end OnlyOne.instance.modify_state OnlyOne.instance.reset end
Java versus Ruby
Java and Ruby have their similarities and their differences so lets compare the two languages.
Ruby | Java |
Interpreted | Compiled to byte code |
Dynamically typed | Statically typed |
Purely object oriented | Distinction between primitives and object types |
Unbounded polymorphism | Inheritance and Interfaces |
Multiple inheritance through mixins | Interfaces |
Syntactic regular-expression support | Not present (can do the same thing in Java by creating a pattern with java.util.regex, etc.) |
Syntactic support for arrays and hashes | Arrays and hashes (HashMap, Hashtable) present in Collections; no special syntax |
nil is an object => no null-pointer exceptions | null means no reference to object |
Everything is a message | Method invocations are compiled, not treated as messages at run time. |
Possible to capture calls to non-existent methods using method_missing | Not possible |
All classes are open to extension | Classes cannot be extended at run time |
Dynamic evaluation of code using eval | Not possible easily |
Reflection is easy | Reflection is much more verbose |
Blocks are closures | Anonymous inner functions are closures but less powerful |
Conclusion
Java doesn’t contain singleton pattern in the language itself, although implementation for the pattern is still possible. While in Ruby the singleton pattern is in the language itself, which became possible since Ruby is a dynamic language through singleton module.