0% found this document useful (0 votes)
9 views16 pages

Understanding the Singleton Pattern

The document discusses the Singleton design pattern, which restricts a class to a single instance and provides a global access point to it. It explains the implementation of the pattern using a private constructor and a static method, and addresses issues related to multithreading and performance optimization. Additionally, it provides examples and suggestions for improving the Singleton pattern in practical applications, particularly in the context of a ChocolateBoiler class.

Uploaded by

Batuhan Ekinci
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views16 pages

Understanding the Singleton Pattern

The document discusses the Singleton design pattern, which restricts a class to a single instance and provides a global access point to it. It explains the implementation of the pattern using a private constructor and a static method, and addresses issues related to multithreading and performance optimization. Additionally, it provides examples and suggestions for improving the Singleton pattern in practical applications, particularly in the context of a ChocolateBoiler class.

Uploaded by

Batuhan Ekinci
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

BIM492 DESIGN PATTERNS

05. SINGLETON PATTERN

One of a Kind Objects


The Little Singleton
How would you create a single object? new MyObject();

And, what if another object wanted to create a Yes, of course.


MyObject? Could it call new on MyObject again?

So as long as we have a class, can we always instantiate Yes. Well, only if it's a public class.
it one or more times?

And if not? Well, if it's not a public class, only classes in the
same package can instantiate it. But they can still
instantiate it more than once.

Hmm, interesting. No, I'd never thought of it, but I guess it makes
Did you know you could do this? sense because it is a legal definition.
public MyClass {
private MyClass() {}
}
2
The Little Singleton
What does it mean? I suppose it is a class that can't be instantiated
because it has a private constructor.

Well, is there ANY object that could use the private Hmm, I think the code in MyClass is the only code
constructor? that could call it. But that doesn't make much sense.

Why not? Because I'd have to have an instance of the class


to call it, but I can't have an instance because no
other class can instantiate it. It's a chicken and
egg problem: I can use the constructor from an
object of type MyClass, but I can never
instantiate that object because no other object
can use "new MyClass()".

3
The Little Singleton
Okay, it was just a thought. MyClass is a class with a static method. We
What does this mean? can call the static method like this:
public MyClass {
public static MyClass getInstance(){} [Link]();
}

Why did you use MyClass, instead of some object name? Well, getInstance() is a static method; in
other words, it is a CLASS method. You need to
use the class name to reference a static method.
Very interesting. What if we put things together. Wow; you sure can.
Now can I instantiate a MyClass?
public MyClass {
private MyClass() {}
public static MyClass getInstance(){
return new MyClass();
}
}
4
The Little Singleton
So, now can you think of a second way to [Link]();
instantiate an object?

Can you finish the code so that only ONE instance of Yes, I think so…
MyClass is ever created?

OK, LET'S FINISH THE CODE!

5
Dissecting the classic Singleton Pattern implementation

public class Singleton {


private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() { }
public static Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
}
6
Code Up Close

7
public class ChocolateBoiler {
private boolean empty;
private boolean boiled;
public ChocolateBoiler() {
The Chocolate Factory
empty = true; Everyone knows that all modern
boiled = false;
} chocolate factories have computer
public void fill() { controlled chocolate boilers. The job
if (isEmpty()) {
empty = false;
of the boiler is to take in chocolate
boiled = false; and milk, bring them to a boil, and
// fill the boiler with a milk/chocolate mixture then pass them on to the next phase
}
}
of making chocolate bars.
public void drain() {
if (!isEmpty() && isBoiled()) {
// drain the boiled milk and chocolate
empty = true;
}
}
public void boil() {
if (!isEmpty() && !isBoiled()) {
// bring the contents to a boil
boiled = true;
}
Here's the controller class for Choc-O-Holic, Inc.'s
} industrial strength Chocolate Boiler. Check out the code;
public boolean isEmpty() { you'll notice they've tried to be very careful to ensure that
return empty;
} bad things don't happen, like draining 500 gallons of
public boolean isBoiled() { unboiled mixture, or filling the boiler when it's already full,
return boiled; or boiling an empty boiler!
}
}
8
Sharpen your pencil

private static ChocolateBoiler uniqueInstance;

private

public static ChocolateBoiler getInstance() {


Can you help Choc-O-Holic improve their if (uniqueInstance == null) {
ChocolateBoiler class by turning it into a }
uniqueInstance = new ChocolateBoiler();

Singleton? return uniqueInstance;


}

9
Singleton Pattern defined
No big surprises there.
But, let's break it down a bit more:
 What's really going on here? We're taking a class and letting it manage a single instance of itself. We're also preventing any other class
from creating a new instance on its own. To get an instance, you've got to go through the class itself.
 We're also providing a global access point to the instance: whenever you need an instance, just query the class and it will hand you back
the single instance. As you've seen, we can implement this so that the Singleton is created in a lazy manner, which is especially important
for resource intensive objects.

10
Houston, we have a problem…
ChocolateBoiler's fill() method was able to start
filling the boiler even though a batch of milk and
chocolate was already boiling! That's 500 gallons
of spilled milk (and chocolate)! What happened!?

Could the addition of threads have caused this? Isn't


it the case that once we've set the uniquelnstance
variable to the sole instance of ChocolateBoiler, all
calls to getlnstance() should return the same
instance? Right?

11
Dealing with multithreading
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here

private Singleton() {}

public static synchronized Singleton getInstance() {


if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
} Good point, and it's actually a little worse than you
// other useful methods here make out the only time synchronization is relevant is
} the first time through this method. In other words,
once we've set the uniqueInstance variable to an
instance of Singleton, we have no further need to
synchronize this method. After the first time through,
synchronization is totally unneeded overhead!
13
Can we improve multithreading?
1. Do nothing if the performance of getInstance() isn’t critical to your application
• Synchronizing getInstance() is straightforward and effective
• Just keep in mind that synchronizing a method can decrease performance by a factor of 100,
so if a high traffic part of your code begins using the method, you may have to reconsider.

2. Move to an eagerly created instance rather than a lazily created one


• Using this approach, we rely on the JVM to create the unique instance of the Singleton when
the class is loaded. The JVM guarantees that the instance will be created before any thread
accesses the static uniquelnstance variable.
public class Singleton {
private static Singleton uniqueInstance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {


return uniqueInstance;
}
}
14
Can we improve multithreading? continued…
3. Use “double-checked locking” to reduce the use of synchronization in getInstance()
• first check to see if an instance is created
• if not THEN synchronize
public class Singleton {
private volatile static Singleton uniqueInstance;

private Singleton() {}

public static Singleton getInstance() {


if (uniqueInstance == null) {
synchronized ([Link]) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton(); If performance is an issue
}

!
in use of getInstance()
}
} method then this method
return uniqueInstance; can drastically reduce the
} overhead.
}
15
Meanwhile, back at the Chocolate Factory
Sharpen your pencil
For each solution, describe its applicability to the problem of fixing the Chocolate Boiler code

Synchronize the getInstance() method


A straightforward technique that is guaranteed to work. We don’t seem to have any
_________________________________________________________________________________
performance concerns with the chocolate boiler, so this would be a good choice.
_________________________________________________________________________________
_________________________________________________________________________________

Use eager instantiation


We are always going to instantiate the chocolate boiler in our code, so statically initializing
_________________________________________________________________________________
the instance would cause no concerns. This solution would work as well as the synchronized
_________________________________________________________________________________
method, although perhaps be less obvious to a developer familiar with the standard pattern
_________________________________________________________________________________

Double-checked locking
Given we have no performance concerns, double-checked locking seems like overkill. In addition,
_________________________________________________________________________________
we’d have to ensure that we are running at least Java 5.
_________________________________________________________________________________
_________________________________________________________________________________

16
Tools for your Design Toolbox
Bullet Points
 The Singleton Pattern ensures you have at most one
instance of a class in your application.
 The Singleton Pattern also provides a global access point
to that instance.
 Java's implementation of the Singleton Pattern makes use
of a private constructor, a static method combined with a
static variable.
 Examine your performance and resource constraints and
carefully choose an appropriate Singleton implementation
for multithreaded applications (and we should consider all
applications multithreaded!).
 Beware of the double-checked locking implementation; it is
not thread-safe in versions before Java 2, version 5.
 Be careful, if you’re using multiple classloaders.

17

You might also like