CSC/ECE 517 Fall 2007/wiki1b 6 c1
Take a case of the Singleton pattern and implement it as succinctly as possible in Ruby and Java. Compare the two implementations in terms of clarity and succinctness. The example should be a "real-world" example. While it may be grossly oversimplified for the purpose of illustration, it should not be totally contrived.
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.
Global Variables versus Singleton
Singletons are often mistaken as global variables. These two are very similar but the main difference between the two is that the Singleton Pattern deals with how to limit instances, while global variables deal with how programmers declare instances. Singletons are frequently mistaken by programmers that are inexperienced because they usually think that the use of Singleton Pattern will solve problems that are associated with global variables.
Benefits of Singleton Pattern
There benefits of using the singleton pattern over other patterns and global variables. When using Singleton Pattern it allows instance control by preventing other objects from instantiating their own copies of the Singleton object which would ensure that all objects access the single instance. Using the Singleton Pattern also gives a little flexibility since the class controls the instantiation process and has the flexibility to change the instantiation process. Singleton Pattern allows reduced name space because the Singleton class can be subclassed,which makes it easier to configure an application with an instance of this extended class. The application can be configures with an instance of the class one needs at run-time.
Several uses appear to Singleton Pattern which include; logger (which is our example here), payment form, applcation preference, many dialogs in the GUI environemt, ... etc.
Implementation
The Singleton pattern is implemented by
- Creating 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.
Class Diagram
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
Invoke a Singletons
The following coding is to invoke a singleton class
Java
LoggerSingleton logger1 = LoggerSingleton.getInstance(); LoggerSingleton logger2 = LoggerSingleton.getInstance(); LoggerSingleton logger3 = new LoggerSingleton(); // compilation error will occur; The constructor is private. System.out.println(logger1); System.out.println(logger2);
Ruby
a = LoggerSingleton.instance b = LoggerSingleton.instance
Test Singletons
The following coding is to test singleton class
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); } }
Ruby
def test_singleton class << OnlyOne.instance def reset # reset state end end OnlyOne.instance.modify_state OnlyOne.instance.reset end
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.