CSC/ECE 517 Fall 2007/wiki1b 6 aa: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(86 intermediate revisions by 2 users not shown)
Line 2: Line 2:




== Singleton Pattern ==


== '''Comparison''' ==
The singleton pattern is one of the [http://en.wikipedia.org/wiki/Design_pattern_(computer_science) design patterns] in [http://en.wikipedia.org/wiki/Software_engineering software engineering]. Singleton pattern limits the instantiation of a class to only one object to ensure that no other instantiation exists. Therefore this pattern is useful when the system needs only one instance of a class but multiple accesses from different parts of the system.
Ruby can implement singleton pattern by simply referencing the singleton module and all its methods will be included. The singleton mixin makes the constructor inaccessible, override clone and dup method, and take care of all the threading complications.  


Java has no mixins, so singleton implementation in Java has to do the following:
=== Singleton Versus Global Variable ===
Singleton is very similar to [http://en.wikipedia.org/wiki/Global_variable global variable]. One might argue that a static global variable could perform equivalently as a singleton class. However, there are differences between singleton and global variable which make them serve different purposes.
 
For one thing, although singletons and global variables can be accessed "globally", singleton pattern puts strict limit in the instantiation of a class. A system cannot instantiate two or more objects of a class when applied singleton. On the contrary, users can always create a number of global variables even if they will produce conflicts. Hence singleton pattern place the responsibility of restricting instantiation on the class itself.
 
For the other thing, because singleton is implemented in class level, developer can add more functionality to perform more complex logic than a global variable. Global variables reflect the way programmers declare variables, while singletons focus on limiting instantiation.
 
=== Pros and Cons of Singleton Pattern ===
 
==== Pros ====
 
* Direct Control: Singleton design pattern has direct control upon the number of [http://en.wikipedia.org/wiki/Instantiation_%28computer_science%29 instantiation].
* Responsibility Shift: Usually it is the programmer's responsibility to assure that there is only one instance, which will cause potential problems when carelessly designed. Utilizing singleton pattern shift the responsibility to the class itself to eliminate such problems.
* Called When Needed: The "single" instance is always created when the getInstance() is called at the first time. Hence singleton is called only when it's really needed.
* Reduced [http://en.wikipedia.org/wiki/Namespace_%28computer_science%29 Namespace]: It saves the name space by reducing the number of global variables that store sole instances.
* Enhanced Extensibility: Singleton pattern can be easily extended to allow any number of objects to be instantiated. Of course, it is still the class that owns the responsibility.
 
==== Cons ====
* Misuse: Sometimes singleton pattern is misused. It is unnecessary to use singleton when it's simpler to pass resource as a reference to the objects rather than letting objects access the resource globally.
* Mix Two Responsibilities to Classes: By using singleton, we make the classes to decide if they are singletons or not. However, someone argues that this responsibility should be taken by a [http://en.wikipedia.org/wiki/Factory_pattern factory] or [http://en.wikipedia.org/wiki/Builder_pattern builder] pattern that encapsulates creation, and limit the instantiation there.
* Banned [http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming Polymorphism]: Singletons tightly couple programmers to the exact type of the singleton object, removing the opportunity to use polymorphism to substitute an alternative.
* Long Last States: Singleton carries states that last throughout the program. This nature can fail the unit test when they shouldn't, or have tests pass just because of the order in which they were run.
* Cause Lazy Programmers: Since singleton is easy to use and good at avoiding problems, programmers might prefer not to think carefully about the appropriate visibility of an object, and just use singleton. However, proper exposure and protection for an object is critical for maintaining flexibility.
 
== UML Class Diagram ==
[[Image:Singleton.JPG]]


1.block off access to constructor by making it private
== Common Uses ==
2.provide a static method for getting an instance of the singleton,
* Record global states
3.prevent cloning by overriding the clone() method explicitly
* Façade objects are often singletons since only one [http://en.wikipedia.org/wiki/Fa%C3%A7ade_pattern Façade] object is required.
4.ensure thread safety
* Implement [http://en.wikipedia.org/wiki/Builder_pattern Builder Pattern], [http://en.wikipedia.org/wiki/Prototype_pattern Prototype Pattern]: : Builder and prototype patterns can use singleton pattern to their implementations.
* Implement [http://en.wikipedia.org/wiki/Abstract_factory_pattern Abastract Factory Pattern]: If all factory objects are stored globally in a singleton object, and all client code goes through the singleton to access the proper factory for object creation, then changing factories is as easy as changing the singleton object.


== '''Example''' ==
== Real World Example ==


Let's take the example of the Earth. Because we only have one earth,it is appropriate to implement the Earth class in singleton.In side the class, currentCondition describes the state (current condition) of the earth.  
Let's take the example of the [http://en.wikipedia.org/wiki/Earth Earth]. Because we only have one earth, it is logical to implement the Earth class as a singleton. Inside the class, "currentCondition" describes the state (current condition) of the earth.  
   
   
'''Ruby Implementation'''
===Ruby Implementation===


<pre>
<pre>
Line 28: Line 54:
</pre>
</pre>


'''Java Implementation'''
===Java Implementation===


<pre>
<pre>
Line 40: Line 66:


  // make the method thread safe
  // make the method thread safe
  public synchronized static Earth getEarth()
  public static Earth getEarth()
  {
  {
    if (ref == null)
    if (ref == null)
Line 48: Line 74:
    return ref;
    return ref;
  }
  }
 
          // override the clone method and throws "CloneNotSupported Exception" if invoked
  public Object clone()
  public Object clone()
throws CloneNotSupportedException
throws CloneNotSupportedException
Line 56: Line 82:


  private String currentCondition="I was beautiful and clean";
  private String currentCondition="I was beautiful and clean";
   
  // get the current condition of the earth
  public String getCurrentCondition(){
  public String getCurrentCondition(){
  return currentCondition;
  return currentCondition;
  }
  }
   
  // set the current condition of the earth
  public void setCurrentCondition(String str){
  public void setCurrentCondition(String str){
  currentCondition=str;
  currentCondition=str;
Line 68: Line 94:
</pre>
</pre>


== '''Test '''==
===Comparison===
'''Ruby Test code'''
 
Ruby can implement singleton pattern by simply referring the singleton module and then all its methods will be included. The singleton [http://en.wikipedia.org/wiki/Mixin mixin] makes the constructor inaccessible, overrides [http://en.wikipedia.org/wiki/Clone_%28Java_method%29 ''clone''] and ''dup'' methods, and takes care of all the [http://en.wikipedia.org/wiki/Thread_%28computer_science%29 threading] complications.
 
Java has no mixins, so singleton implementation in Java has to do the following:
 
* Block off access to constructor by making it private
* Provide a static method for getting an instance of the singleton,
* Prevent cloning by overriding the ''clone()'' method explicitly
* Ensure thread safety
 
==== Succinctness ====
In terms of succinctness, Ruby obviously wins over Java. Only one line of code "include Singleton" enables all the functionalities while Java use a dozen of lines to accomplish.
 
==== Clarity ====
In terms of clarity, Ruby also surpasses Java. For Ruby, after including singleton mixin, it is ready to create/get the only object using "instance" method. However, in Java, there is no uniform method to create/get the only object of the singleton class. Since it is the developer's responsibility to implement the singleton class, different methods could be used (such as "getInstance" "Instance" "returnInstance") to create/get the object.
 
== Test ==
 
We create class [http://en.wikipedia.org/wiki/People ''People''] to test the singleton class ''Earth''. In Java, ''People'' class has a [http://en.wikipedia.org/wiki/Pollute ''pollute''] method, which accepts Earth object as parameter. Thanks to the [http://en.wikipedia.org/wiki/Duck_typing duck-typing] feature, the parameter type does not matter much in Ruby . We try to test if there is only one earth object created. The test goes through the following steps:
* Create earth1 and earth2 using object creation mechanism of the Earth class.
* Print the states of earth1 and earth2 (currentCondition) before invoking ''People'''s ''pollute'' method.
* Invoke ''People'''s ''pollute'' method on earth1.
* Print the final states of earth1 and earth2 (currentCondition).
 
===Ruby Test Code===
<pre>
<pre>
class People
class People
def pollute(a)  # pollute an earth object
a.currentCondition="i am old and polluted"
end


def test
def pollute(a)  # pollute an earth object
p=People.new
  a.currentCondition="i am dirty and polluted"
earth1=Earth.instance
end
earth2=Earth.instance
 
def test
  p=People.new
 
  #suppose we have two "earthes"
  earth1=Earth.instance
  earth2=Earth.instance
  earth1.currentCondition="I am beautiful and clean"
 
  #both earth1 and earth2 are "beautiful and clean"
  puts "earth1 says: " + earth1.currentCondition
  puts "earth2 says: " + earth2.currentCondition


earth1.currentCondition="I am young and clean"
  # we (people) pollute earth1  
puts "Earth1 says: " + earth1.currentCondition
  p.pollute(earth1)
puts "Earth2 says: " + earth2.currentCondition
  puts "After people pollute earth1"


# pollute earth1
  #both earth1 and earth2 are "dirty and polluted", because earth1==earth2
p.pollute(earth1)
  puts "earth1 says: " + earth1.currentCondition
puts "After people pollute earth1"
  puts "earth2 says: " + earth2.currentCondition
end


puts "Earth1 says: " + earth1.currentCondition
puts "Earth2 says: " + earth2.currentCondition
end
end
end


Line 97: Line 154:
p.test
p.test
</pre>
</pre>
'''
 
Java test code'''
===Java Test Code===
<pre>
<pre>


public class People {
public class People {
public void pollute(Earth earth){
public void pollute(Earth earth){
earth.getEarth().setCurrentCondition("I am dirty and polluted");
earth.getEarth().setCurrentCondition("I am dirty and polluted");
}
}
public static void main(String args[]){
public static void main(String args[]){
People p=new People();
People p=new People();
                // suppose we have two earths earth1 and earth2
Earth earth1= Earth.getEarth();
Earth earth1= Earth.getEarth();
Earth earth2= Earth.getEarth();
Earth earth2= Earth.getEarth();
 
                // and both earth1 and earth2 are "beautiful and clean"
System.out.println("earth1 says: " +earth1.getCurrentCondition());
System.out.println("earth1 says: " +earth1.getCurrentCondition());
System.out.println("earth2 says: " +earth2.getCurrentCondition());
System.out.println("earth2 says: " +earth2.getCurrentCondition());
 
                // suppose we only pollute earth1
p.pollute(earth1);
p.pollute(earth1);
System.out.println("After people pollute earth1");
System.out.println("After people pollute earth1");
 
                // earth1 will be "dirty and polluted"
System.out.println("earth1 says: " +earth1.getCurrentCondition());
System.out.println("earth1 says: " +earth1.getCurrentCondition());
                // earth2 is also "dirty and polluted" Why? we only have one earth earth1==earth2!
System.out.println("earth2 says: " +earth2.getCurrentCondition());
System.out.println("earth2 says: " +earth2.getCurrentCondition());
Line 124: Line 188:
</pre>
</pre>


=== Test Result ===
Both the Java code and the Ruby code will produce the following output
<pre>
earth1 says: I was beautiful and clean
earth2 says: I was beautiful and clean
After people pollute earth1
earth1 says: I am dirty and polluted
earth2 says: I am dirty and polluted


== Test Result ==
Both the java code and the ruby code will produce the following output
<pre>
<font BGCOLOR="black">
earth1 says: I was beautiful and clean
earth2 says: I was beautiful and clean
After people pollute earth1
earth1 says: I am dirty and polluted
earth2 says: I am dirty and polluted
</font>
</pre>
</pre>
Before invoking ''People'''s ''pollute'' method, earth1 and earth2 are "beautiful and clean", and after invoking the method on earth1, both earth 1 and earth2 change to be "dirty and polluted". This illustrates that actually only one Earth object was created. '''''"We have only one earth"'''''


= References =
== References ==
 
===Books===
#[http://www.amazon.com/Programming-Ruby-Pragmatic-Programmers-Second/dp/0974514055 Programming Ruby: The programmatic programmer’s guide]
#[http://www.amazon.com/Programming-Ruby-Pragmatic-Programmers-Second/dp/0974514055 Programming Ruby: The programmatic programmer’s guide]
#[http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124 Head First Design Patterns]
#[http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124 Head First Design Patterns]
===Links===
#[http://www.ruby-doc.org/stdlib/libdoc/singleton/rdoc/index.html - Ruby standard library documentation]
#[http://en.wikipedia.org/wiki/Design_pattern_(computer_science) Design Patterns - Wikipedia]
#[http://en.wikipedia.org/wiki/Design_pattern_(computer_science) Design Patterns - Wikipedia]
#[http://cwilliams.textdriven.com/articles/2006/10/31/patterns-in-ruby-singleton-pattern - Patterns in Ruby: Singleton Pattern]
#[http://sern.ucalgary.ca/courses/seng/443/W02/assignments/Builder&Singleton/singleton.html Singleton Pattern Created By: Deema Temraz]
 
#[http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx Why Singletons Are Evil]
===See Also===
== External Links ==
 
#[http://www.ruby-doc.org/stdlib/libdoc/singleton/rdoc/index.html Ruby Standard Library Documentation]
#[]
#[http://cwilliams.textdriven.com/articles/2006/10/31/patterns-in-ruby-singleton-pattern Patterns in Ruby: Singleton Pattern]
#[http://www.beginner-java-tutorial.com/singleton.html Java Singleton Pattern]
#[http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html Simply Singleton: JavaWorld]
#[http://www.beginner-java-tutorial.com/singleton.html Java Singleton Design Pattern]
#[http://c2.com/cgi/wiki?SingletonPattern Singleton Pattern]
#[http://www.castle-cadenza.demon.co.uk/single.htm Singleton Pattern]

Latest revision as of 02:07, 11 October 2007

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 (i.e., should not raise the question, Why would anyone ever want to do that?).


Singleton Pattern

The singleton pattern is one of the design patterns in software engineering. Singleton pattern limits the instantiation of a class to only one object to ensure that no other instantiation exists. Therefore this pattern is useful when the system needs only one instance of a class but multiple accesses from different parts of the system.

Singleton Versus Global Variable

Singleton is very similar to global variable. One might argue that a static global variable could perform equivalently as a singleton class. However, there are differences between singleton and global variable which make them serve different purposes.

For one thing, although singletons and global variables can be accessed "globally", singleton pattern puts strict limit in the instantiation of a class. A system cannot instantiate two or more objects of a class when applied singleton. On the contrary, users can always create a number of global variables even if they will produce conflicts. Hence singleton pattern place the responsibility of restricting instantiation on the class itself.

For the other thing, because singleton is implemented in class level, developer can add more functionality to perform more complex logic than a global variable. Global variables reflect the way programmers declare variables, while singletons focus on limiting instantiation.

Pros and Cons of Singleton Pattern

Pros

  • Direct Control: Singleton design pattern has direct control upon the number of instantiation.
  • Responsibility Shift: Usually it is the programmer's responsibility to assure that there is only one instance, which will cause potential problems when carelessly designed. Utilizing singleton pattern shift the responsibility to the class itself to eliminate such problems.
  • Called When Needed: The "single" instance is always created when the getInstance() is called at the first time. Hence singleton is called only when it's really needed.
  • Reduced Namespace: It saves the name space by reducing the number of global variables that store sole instances.
  • Enhanced Extensibility: Singleton pattern can be easily extended to allow any number of objects to be instantiated. Of course, it is still the class that owns the responsibility.

Cons

  • Misuse: Sometimes singleton pattern is misused. It is unnecessary to use singleton when it's simpler to pass resource as a reference to the objects rather than letting objects access the resource globally.
  • Mix Two Responsibilities to Classes: By using singleton, we make the classes to decide if they are singletons or not. However, someone argues that this responsibility should be taken by a factory or builder pattern that encapsulates creation, and limit the instantiation there.
  • Banned Polymorphism: Singletons tightly couple programmers to the exact type of the singleton object, removing the opportunity to use polymorphism to substitute an alternative.
  • Long Last States: Singleton carries states that last throughout the program. This nature can fail the unit test when they shouldn't, or have tests pass just because of the order in which they were run.
  • Cause Lazy Programmers: Since singleton is easy to use and good at avoiding problems, programmers might prefer not to think carefully about the appropriate visibility of an object, and just use singleton. However, proper exposure and protection for an object is critical for maintaining flexibility.

UML Class Diagram

Common Uses

  • Record global states
  • Façade objects are often singletons since only one Façade object is required.
  • Implement Builder Pattern, Prototype Pattern: : Builder and prototype patterns can use singleton pattern to their implementations.
  • Implement Abastract Factory Pattern: If all factory objects are stored globally in a singleton object, and all client code goes through the singleton to access the proper factory for object creation, then changing factories is as easy as changing the singleton object.

Real World Example

Let's take the example of the Earth. Because we only have one earth, it is logical to implement the Earth class as a singleton. Inside the class, "currentCondition" describes the state (current condition) of the earth.

Ruby Implementation

require 'Singleton'

class Earth
  include Singleton  # include singleton mixin
  attr_accessor :currentCondition
end

Java Implementation


public class Earth {
	  private Earth()
	  {
	   // override the contructor to make it private
	  }
	  private static Earth ref;

	  // make the method thread safe
	  public static Earth getEarth()
	  {
	    if (ref == null)
            synchronized (Earth.class) {   // for thread-safety
                if (ref == null) ref = new Earth ( );
          } 	
	    return ref;
	  }
          // override the clone method and throws "CloneNotSupported Exception" if invoked
	  public Object clone()
		throws CloneNotSupportedException
	  {
	    throw new CloneNotSupportedException(); 
	  }

	  private String currentCondition="I was beautiful and clean";
	  // get the current condition of the earth
	  public String getCurrentCondition(){
		  return currentCondition;
	  }
	  // set the current condition of the earth
	  public void setCurrentCondition(String str){
		  currentCondition=str;
	  }
	  
	}

Comparison

Ruby can implement singleton pattern by simply referring the singleton module and then all its methods will be included. The singleton mixin makes the constructor inaccessible, overrides clone and dup methods, and takes care of all the threading complications.

Java has no mixins, so singleton implementation in Java has to do the following:

  • Block off access to constructor by making it private
  • Provide a static method for getting an instance of the singleton,
  • Prevent cloning by overriding the clone() method explicitly
  • Ensure thread safety

Succinctness

In terms of succinctness, Ruby obviously wins over Java. Only one line of code "include Singleton" enables all the functionalities while Java use a dozen of lines to accomplish.

Clarity

In terms of clarity, Ruby also surpasses Java. For Ruby, after including singleton mixin, it is ready to create/get the only object using "instance" method. However, in Java, there is no uniform method to create/get the only object of the singleton class. Since it is the developer's responsibility to implement the singleton class, different methods could be used (such as "getInstance" "Instance" "returnInstance") to create/get the object.

Test

We create class People to test the singleton class Earth. In Java, People class has a pollute method, which accepts Earth object as parameter. Thanks to the duck-typing feature, the parameter type does not matter much in Ruby . We try to test if there is only one earth object created. The test goes through the following steps:

  • Create earth1 and earth2 using object creation mechanism of the Earth class.
  • Print the states of earth1 and earth2 (currentCondition) before invoking People's pollute method.
  • Invoke People's pollute method on earth1.
  • Print the final states of earth1 and earth2 (currentCondition).

Ruby Test Code


class People

 def pollute(a)  # pollute an earth object
  a.currentCondition="i am dirty and polluted"
 end

 def test
  p=People.new

  #suppose we have two "earthes"
  earth1=Earth.instance
  earth2=Earth.instance
  earth1.currentCondition="I am beautiful and clean"

  #both earth1 and earth2 are "beautiful and clean"
  puts "earth1 says: " + earth1.currentCondition
  puts "earth2 says: " + earth2.currentCondition

  # we (people) pollute earth1 
  p.pollute(earth1)
  puts "After people pollute earth1"

  #both earth1 and earth2 are "dirty and polluted", because earth1==earth2
  puts "earth1 says: " + earth1.currentCondition
  puts "earth2 says: " + earth2.currentCondition
 end

end

p=People.new
p.test

Java Test Code


public class People {
	public void pollute(Earth earth){
		earth.getEarth().setCurrentCondition("I am dirty and  polluted");
	}
	public static void main(String args[]){
		People p=new People();

                // suppose we have two earths earth1 and earth2
		Earth earth1= Earth.getEarth();
		Earth earth2= Earth.getEarth();	

                // and both earth1 and earth2 are "beautiful and clean"
		System.out.println("earth1 says: " +earth1.getCurrentCondition());
		System.out.println("earth2 says: " +earth2.getCurrentCondition());	

                // suppose we only pollute earth1
		p.pollute(earth1);
		System.out.println("After people pollute earth1");

                // earth1 will be "dirty and polluted"
		System.out.println("earth1 says: " +earth1.getCurrentCondition());

                // earth2 is also "dirty and polluted" Why? we only have one earth earth1==earth2!
		System.out.println("earth2 says: " +earth2.getCurrentCondition());
		
	}
}

Test Result

Both the Java code and the Ruby code will produce the following output


 earth1 says: I was beautiful and clean
 earth2 says: I was beautiful and clean

 After people pollute earth1

 earth1 says: I am dirty and polluted
 earth2 says: I am dirty and polluted

Before invoking People's pollute method, earth1 and earth2 are "beautiful and clean", and after invoking the method on earth1, both earth 1 and earth2 change to be "dirty and polluted". This illustrates that actually only one Earth object was created. "We have only one earth"

References

  1. Programming Ruby: The programmatic programmer’s guide
  2. Head First Design Patterns
  3. Design Patterns - Wikipedia
  4. Singleton Pattern Created By: Deema Temraz
  5. Why Singletons Are Evil

External Links

  1. Ruby Standard Library Documentation
  2. Patterns in Ruby: Singleton Pattern
  3. Java Singleton Pattern
  4. Simply Singleton: JavaWorld
  5. Java Singleton Design Pattern
  6. Singleton Pattern
  7. Singleton Pattern