Chapter 5. The Singleton Pattern: One of a Kind Objects

Images

Our next stop is the Singleton Pattern, our ticket to creating one-of-a-kind objects for which there is only one instance, ever. You might be happy to know that of all patterns, the Singleton is the simplest in terms of its class diagram; in fact, the diagram holds just a single class! But don’t get too comfortable; despite its simplicity from a class design perspective, it’s going to require some deep object-oriented thinking in its implementation. So put on that thinking cap, and let’s get going.

Images

Developer: What use is that?

Guru: There are many objects we only need one of: thread pools, caches, dialog boxes, objects that handle preferences and registry settings, objects used for logging, and objects that act as device drivers to devices like printers and graphics cards. In fact, for many of these types of objects, if we were to instantiate more than one we’d run into all sorts of problems like incorrect program behavior, overuse of resources, or inconsistent results.

Developer: Okay, so maybe there are classes that should only be instantiated once, but do I need a whole chapter for this? Can’t I just do this by convention or by global variables? You know, like in Java, I could do it with a static variable.

Guru: In many ways, the Singleton Pattern is a convention for ensuring one and only one object is instantiated for a given class. If you’ve got a better one, the world would like to hear about it; but remember, like all patterns, the Singleton Pattern is a time-tested method for ensuring only one object gets created. The Singleton Pattern also gives us a global point of access, just like a global variable, but without the downsides.

Developer: What downsides?

Guru: Well, here’s one example: if you assign an object to a global variable, then that object might be created when your application begins. Right? What if this object is resource intensive and your application never ends up using it? As you will see, with the Singleton Pattern, we can create our objects only when they are needed.

Developer: This still doesn’t seem like it should be so difficult.

Guru: If you’ve got a good handle on static class variables and methods as well as access modifiers, it’s not. But, in either case, it is interesting to see how a Singleton works, and, as simple as it sounds, Singleton code is hard to get right. Just ask yourself: how do I prevent more than one object from being instantiated? It’s not so obvious, is it?

The Little Singleton

A small Socratic exercise in the st yle of The Little Lisper

How would you create a single object? new MyObject();
And, what if another object wanted to create a MyObject? Could it call new on MyObject again? Yes, of course.
So as long as we have a class, can we always instantiate it one or more times? Yes. Well, only if it’s a public class.
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. Did you know you could do this?
public MyClass {

   
   private MyClass() {}

}
No, I’d never thought of it, but I guess it makes sense because it is a legal definition.
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 constructor? Hmm, I think the code in MyClass is the only code 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()”.

Okay. It was just a thought.
What does this mean?

public MyClass {


   public static MyClass getInstance() {
   
   }
}
MyClass is a class with a static method. We can call the static method like this: MyClass.getInstance();
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.
Now can I instantiate a MyClass?

public MyClass {
 

   private MyClass() {}


   public static MyClass getInstance() {

       return new MyClass();
   }
}
Wow, you sure can.
So, now can you think of a second way to instantiate an object? MyClass.getInstance();
Can you finish the code so that only ONE instance of MyClass is ever created? Yes, I think so...

(You’ll find the code on the next page.)

Dissecting the classic Singleton Pattern implementation

Images

Images Patterns Exposed

This week’s interview: Confessions of a Singleton

HeadFirst: Today we are pleased to bring you an interview with a Singleton object. Why don’t you begin by telling us a bit about yourself.

Singleton: Well, I’m totally unique; there is just one of me!

HeadFirst: One?

Singleton: Yes, one. I’m based on the Singleton Pattern, which assures that at any time there is only one instance of me.

HeadFirst: Isn’t that sort of a waste? Someone took the time to develop a full-blown class and now all we can get is one object out of it?

Singleton: Not at all! There is power in ONE. Let’s say you have an object that contains registry settings. You don’t want multiple copies of that object and its values running around—that would lead to chaos. By using an object like me you can assure that every object in your application is making use of the same global resource.

HeadFirst: Tell us more...

Singleton: Oh, I’m good for all kinds of things. Being single sometimes has its advantages you know. I’m often used to manage pools of resources, like connection or thread pools.

HeadFirst: Still, only one of your kind? That sounds lonely.

Singleton: Because there’s only one of me, I do keep busy, but it would be nice if more developers knew me—many developers run into bugs because they have multiple copies of objects floating around they’re not even aware of.

HeadFirst: So, if we may ask, how do you know there is only one of you? Can’t anyone with a new operator create a “new you”?

Singleton: Nope! I’m truly unique.

HeadFirst: Well, do developers swear an oath not to instantiate you more than once?

Singleton: Of course not. The truth be told... well, this is getting kind of personal but... I have no public constructor.

HeadFirst: NO PUBLIC CONSTRUCTOR! Oh, sorry, no public constructor?

Singleton: That’s right. My constructor is declared private.

HeadFirst: How does that work? How do you EVER get instantiated?

Singleton: You see, to get a hold of a Singleton object, you don’t instantiate one, you just ask for an instance. So my class has a static method called getInstance(). Call that, and I’ll show up at once, ready to work. In fact, I may already be helping other objects when you request me.

HeadFirst: Well, Mr. Singleton, there seems to be a lot under your covers to make all this work. Thanks for revealing yourself and we hope to speak with you again soon!

The Chocolate Factory

Everyone knows that all modern chocolate factories have computer-controlled chocolate boilers. The job of the boiler is to take in chocolate and milk, bring them to a boil, and then pass them on to the next phase of making chocolate bars.

Here’s the controller class for Choc-O-Holic, Inc.’s industrial strength Chocolate Boiler. Check out the code; you’ll notice they’ve tried to be very careful to ensure that bad things don’t happen, like draining 500 gallons of unboiled mixture, or filling the boiler when it’s already full, or boiling an empty boiler!

Images
Images

Singleton Pattern defined

Now that you’ve got the classic implementation of Singleton in your head, it’s time to sit back, enjoy a bar of chocolate, and check out the finer points of the Singleton Pattern.

Let’s start with the concise definition of the pattern:

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.

Okay, let’s check out the class diagram:

Images

Hershey, PA, we have a problem...

It looks like the Chocolate Boiler has let us down; despite the fact we improved the code using Classic Singleton, somehow the 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!?

Images
Note

Could the addition of threads have caused this? Isn’t it the case that once we’ve set the uniqueInstance variable to the sole instance of ChocolateBoiler, all calls to getInstance() should return the same instance? Right?

BE the JVM

Images

We have two threads, each executing this code. Your job is to play the JVM and determine whether there is a case in which two threads might get ahold of different boiler objects. Hint: you really just need to look at the sequence of operations in the getInstance() method and the value of uniqueInstance to see how they might overlap. Use the code magnets to help you study how the code might interleave to create two boiler objects.

Images
Note

Make sure you check your answer on page 190 before continuing!

Images

Dealing with multithreading

Our multithreading woes are almost trivially fixed by making getInstance() a synchronized method:

Images
Images

Good point, and it’s actually a little worse than you 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!

Can we improve multithreading?

For most Java applications, we obviously need to ensure that the Singleton works in the presence of multiple threads. But, it is expensive to synchronize the getInstance() method, so what do we do?

Well, we have a few options...

1. Do nothing if the performance of getInstance() isn’t critical to your application.

That’s right; if calling the getInstance() method isn’t causing substantial overhead for your application, forget about it. 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 getInstance(), you may have to reconsider.

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

If your application always creates and uses an instance of the Singleton or the overhead of creation and runtime aspects of the Singleton are not onerous, you may want to create your Singleton eagerly, like this:

Images

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 uniqueInstance variable.

3. Use “double-checked locking” to reduce the use of synchronization in getInstance().

With double-checked locking, we first check to see if an instance is created, and if not, THEN we synchronize. This way, we only synchronize the first time through, just what we want.

Let’s check out the code:

Images

If performance is an issue in your use of the getInstance() method then this method of implementing the Singleton can drastically reduce the overhead.

Meanwhile, back at the Chocolate Factory...

While we’ve been off diagnosing the multithreading problems, the chocolate boiler has been cleaned up and is ready to go. But first, we have to fix the multithreading problems. We have a few solutions at hand, each with different tradeoffs, so which solution are we going to employ?

Images

Congratulations!

At this point, the Chocolate Factory is a happy customer and Choc-O-Holic was glad to have some expertise applied to their boiler code. No matter which multithreading solution you applied, the boiler should be in good shape with no more mishaps. Congratulations. You’ve not only managed to escape 500lbs of hot chocolate in this chapter, but you’ve been through all the potential problems of the Singleton.

Images

Ah, good idea!

Many of the problems we’ve discussed—worrying about synchronization, class loading issues, reflection, and serialization/deserialization issues—can all be solved by using an enum to create your Singleton. Here’s how you’d do that:

 public enum Singleton {
     UNIQUE_INSTANCE;
     // more useful fields here
 }
 public class SingletonClient {
       public static void main(String[] args) {
              Singleton singleton = Singleton.UNIQUE_INSTANCE;
              // use the singleton here
       }
}

And back in the old days, when we had to walk to school, up-hill, in the snow, in both directions, Java didn’t have enums.

Yep, that’s all there is to it. Simplest Singelton ever, right? Now, you might be asking, why did we go through all that earlier with creating a Singleton class with a getInstance() method and then synchronizing, and so on... we did that so you really, truly understand how Singleton works. Now you know, you can go off and use enum whenever you need a Singleton, and still be able to ace that Java interview if the question pops up: “How do you implement a Singleton without using enum?”

Tools for your Design Toolbox

You’ve now added another pattern to your toolbox. Singleton gives you another method of creating objects—in this case, unique objects.

Images
Images

As you’ve seen, despite its apparent simplicity, there are a lot of details involved in the Singleton’s implementation. After reading this chapter, though, you are ready to go out and use Singleton in the wild.

Images Design Patterns Crossword

Sit back, open that case of chocolate that you were sent for solving the multithreading problem, and have some downtime working on this little crossword puzzle; all of the solution words are from this chapter.

Images

ACROSS

1. It was “one of a kind.”

2. Added to chocolate in the boiler.

8. An incorrect implementation caused this to overflow.

10. Singleton provides a single instance and __________ (three words).

12. Flawed multi-threading approach if not using Java 5 or later.

13. Chocolate capital of the USA.

14. One advantage over global variables: ________ creation.

15. Company that produces boilers.

16. To totally defeat the new constructor, we have to declare the constructor __________.

DOWN

1. Multiple __________ can cause problems.

3. A Singleton is a class that manages an instance of ________.

4. If you don’t need to worry about lazy instantiation, you can create your instance __________.

5. Prior to Java 1.2, this can eat your Singletons (two words).

6. The Singleton was embarrassed it had no public __________.

7. The classic implementation doesn’t handle this.

9. Singleton ensures only one of these exists.

11. The Singleton Pattern has one.

BE the JVM Solution

Images

Images Design Patterns Crossword Solution

Images
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset