Java Design Patterns Singleton
Singleton Overview
In this example SingleSpoon class holds one instance of SingleSpoon in "private static SingleSpoon theSpoon;". The SingleSpoon class determines the spoons availability using "private static boolean theSpoonIsAvailable = true;" The first time SingleSpoon.getTheSpoon() is called it creates an instance of a SingleSpoon. The SingleSpoon can not be distributed again until it is returned with SingleSpoon.returnTheSpoon().
If you were to create a spoon "pool" you would have the same basic logic as shown, however multiple spoons would be distributed. The variable theSpoon would hold an array or collection of spoons. The variable theSpoonIsAvaialable would become a counter of the number of available spoons.
Please also note that this example is not thread safe. I think that to make it thread safe all you would need is to make the getTheSpoon() method synchronized. Many thanks to Brian K. for pointing this out.
SingleSpoon.java - a Singleton
public class SingleSpoon
{
private Soup soupLastUsedWith;
private static SingleSpoon theSpoon;
private static boolean theSpoonIsAvailable = true;
private SingleSpoon() {}
public static SingleSpoon getTheSpoon() {
if (theSpoonIsAvailable) {
if (theSpoon == null) {
theSpoon = new SingleSpoon();
}
theSpoonIsAvailable = false;
return theSpoon;
} else {
return null;
//spoon not available,
// could throw error or return null (as shown)
}
}
public String toString() {
return "Behold the glorious single spoon!";
}
public static void returnTheSpoon() {
theSpoon.cleanSpoon();
theSpoonIsAvailable = true;
}
public Soup getSoupLastUsedWith() {
return this.soupLastUsedWith;
}
public void setSoupLastUsedWith(Soup soup) {
this.soupLastUsedWith = soup;
}
public void cleanSpoon() {
this.setSoupLastUsedWith(null);
}
}
TestSingleSpoon.java - testing the singleton
class TestSingleSpoon {
public static void main(String[] args) {
System.out.println("First person getting the spoon");
SingleSpoon spoonForFirstPerson =
SingleSpoon.getTheSpoon();
if (spoonForFirstPerson != null)
System.out.println(spoonForFirstPerson);
else
System.out.println("No spoon was available");
System.out.println("");
System.out.println("Second person getting a spoon");
SingleSpoon spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");
System.out.println("");
System.out.println("First person returning the spoon");
spoonForFirstPerson.returnTheSpoon();
spoonForFirstPerson = null;
System.out.println("The spoon was returned");
System.out.println("");
System.out.println("Second person getting a spoon");
spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");
}
} Test Results
First person getting the spoon Behold the glorious single spoon!
Second person getting a spoon No spoon was available
First person returning the spoon The spoon was returned
Second person getting a spoon Behold the glorious single spoon!
UML
References
| Comments Comments are left by visitors to FluffyCat.com, are not endorsed by FluffyCat.com, and may or may not be accurate. |
| Comment by david_david Rate this Comment |
If we are using the singleton class like specified in "Comment by gamlidekgamlidek"
|
| Comment by archive Rate this Comment |
I realy appreciate the Java Patterns on your site. Since I like to play with the examples I simply copied it into text fils and compiled them. I found a few minor problems you may want to know about:
|
| Comment by Rath N Rate this Comment |
public class TestString {
|
| Comment by gamlidek Rate this Comment |
A good implementation of a simple pure singleton in Java needs to account for the clone method, as mentioned by archive above, and shouldn't hold a lock on the object like you're doing. Also, note that two getInstance() calls can occur at the same time possible causing two instances to get created, so I made the getInstance() method synchronized. BTW, if you have areas that require synchronization, then put it in a syncronized block.
|
| Comment by ram25 Rate this Comment |
There still needs some correction. We need to synchronize the check to null in the getTheSpoon() method. Simpler yet make the function synchronized. This is because, call A to the function could complete the check and be stalled by the OS scheduler, and so with call B. Now that in that situation there are two function calls that think the instance variable is still null and eventually instantiate the instance variable leading to a race condition. |
| Comment by archive Rate this Comment |
Just found your site. It's a great resource so has gone straight into my
|
| Sign In |
| to add your own comment |