CSC/ECE 517 Fall 2010/ch3 3f sm: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 79: Line 79:


Ruby is a dynamically typed object oriented language. This means type checking happens at run time. Implementing the singleton pattern in
Ruby is a dynamically typed object oriented language. This means type checking happens at run time. Implementing the singleton pattern in
ruby has the same aspects as in java. So we can just write the ruby equivalent of the code above and we have the ruby singleton pattern.
Ruby has the same aspects as in Java. So we can just write the ruby equivalent of the code above and we have the ruby singleton pattern.
Just to show how it looks we have it down here.  
Just to show how it looks we have it down here.  


Line 110: Line 110:


The include Singleton statement in the above code includes all the methods of the Singleton module. The instance method we saw in the previous example is implemented in the
The include Singleton statement in the above code includes all the methods of the Singleton module. The instance method we saw in the previous example is implemented in the
Singleton module. This module uses the lazy instantiation method.
Singleton module. This module uses the lazy instantiation method.
 
==Conclusion==
==Conclusion==
Singleton pattern in both languages as seen above has to take care of a lot of implementation details. It is counter intuitive to the concept of objects and classes.
Singleton pattern in both languages as seen above has to take care of a lot of implementation details. It is counter intuitive to the concept of objects and classes.

Revision as of 02:47, 7 October 2010

Introduction

Singleton pattern has the simplest class diagram among all the design patterns discussed by the gang of four. It has just one class. It has some interesting characteristics. Lets start with the definition itself.  

Singleton
Ensures a class has only one instance, and provides a global point of access to it.

The definiton can be explained as "we can have one and only one instance of the class". Singleton pattern is useful in cases where you need to interact with input and output devices, to maintain thread pools, to log events in a single log file etc. Although the class diagram of the singleton class seems simple, it's implementation can be quite a task. To make sure its peculiar behavior of having just one object and serving up the same object when requested makes it so. Classes are naturally designed in a way that we create many instances of them. So we have to move against this and make sure we have only one object. We have to take care of multi-threading scenarios, subclassing etc. We will discuss the implementation of singleton pattern in dynamic and static languages below.

Singleton Pattern in Java

Java is a statically typed object oriented language. Among other things this means that type checking is done in compile time in Java.

Implementation

Singleton pattern in java is implemented considering the 4 steps mention below.
  • Create a default constructor and make it private.
  • Create a method for getting the reference to the singleton object.
  • Make the access method synchronized to prevent thread issues.
  • Prevent cloning of the object by overriding the object clone method.
class SingletonObject {

	private static SingletonObject myObject;
	
	private SingletonObject() {
		// Optional Code
	}
	public static SingletonObject getSingletonObject() {
		if (myObject == null) {
			myObject = new SingletonObject();
		}
		return myObject;
	}
}

In this code we have followed the first two steps. We are making the default constructor private. This means that the constructor can be accessed only by other methods inside the class. This prevents a developer from creating an object of the class by using the 'SingletonObject myObject = new SingletonObject()'. To get the object of the singleton class the developer must call the SingletonObject.instance() method. In the instance method a new object is being created if a singleton doesn’t exist, otherwise the existing reference to SingletonObject is returned. This way the reference to same object is returned every time the instance method is called. In the above example we are using lazy instantiation, that means the object is created only when the for the first time the initialize method is called. We could have also used early instantiation in that case the object would be instantiated when the class is loaded.

class SingletonObject {

	private static SingletonObject myObject;

	private SingletonObject() {
		//	 Optional Code
	}
	public static synchronized SingletonObjec myObject() {
		if (myObject == null) {
			myObject = new SingletonClass();
		}
		return myObject;
	}
	public Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
	}
}

Synchronization and Cloning
The above code seems to be good enough for a singleton pattern, but when we take a closer look we realize that when multiple threads access this instance method there is a possibility that more than one object can get created. So we need to make this method synchronized. This makes sure that only one thread can access this function at a time and thus ensuring that only object is ever created of the SingletonObject class. Synchronizing the singleton method has some consequences. This may result in performance loss if the singleton instance method is being accessed a lot of times in our over all application. This may be the case in some singletons which manage I/O operations, write logs to the same file etc. A closerlook at the code can tell us that synchronizing access to the instance() method is not necessary after the object is created, that is after the first call to the initialize() method.

We can still create a copy of the singleton by cloning it using the Object’s clone method. It can be done like this 'SingletonObject clonedObject = (SingletonObject) obj.clone();'. To avoid this we have to override the clone method as shown above. We can just throw an exception when this method is called.

Singleton pattern in Ruby

Ruby is a dynamically typed object oriented language. This means type checking happens at run time. Implementing the singleton pattern in Ruby has the same aspects as in Java. So we can just write the ruby equivalent of the code above and we have the ruby singleton pattern. Just to show how it looks we have it down here.

class SingletonObject
  def initialize
   #option code
  end
  
  @@instance = SingletonObject.new

  def self.instance
    return @@instance
  end
  
  private_class_method :new
end

This is how singleton is implemented in ruby. In this case we are using static instantiation as you can see. We might have to use mutex and lock the block of code which runs initialize. Its still a lot of things to care about, so ruby provides a simpler way to do it. Ruby standard library has a singleton module which we can use. It defines the initialize method for us. It does lazy instantiation of the singleton object too.

require 'singleton'

class SingletonObject
  include Singleton
end

The include Singleton statement in the above code includes all the methods of the Singleton module. The instance method we saw in the previous example is implemented in the Singleton module. This module uses the lazy instantiation method.

Conclusion

Singleton pattern in both languages as seen above has to take care of a lot of implementation details. It is counter intuitive to the concept of objects and classes. For example subclassing is another important thing to remember when we use the singleton pattern. We cannot subclass the singleton class as it may lead to duplication, unnecessary consequences in the lower classes etc. Implementation of singleton pattern mostly decides on what tradeoff we are ready to make. If we dont call the initialize method too many times then we can make do with having it being synchronized. If lazy instantiation is necessary then we have to tradeoff the convinience that comes with using static variables. So now we have learned to implement the singleton pattern in static an dynamic variables.

References