CHAPTER 3

image

Singleton Patterns

GoF Definition: Ensure a class only has one instance, and provide a global point of access to it.

Concept

A particular class should have only one instance. We will use only that instance whenever we are in need.

Real-Life Example

Suppose you are a member of a cricket team. And in a tournament your team is going to play against another team. As per the rules of the game, the captain of each side must go for a toss to decide which side will bat (or bowl) first. So, if your team does not have a captain, you need to elect someone as a captain first. And at the same time, your team cannot have more than one captain.

Computer World Example

In a software system sometimes we may decide to use only one file system. Usually we may use it for the centralized management of resources.

Illustration

In this example, we have made the constructor private first, so that we cannot instantiate in normal fashion. When we attempt to create an instance of the class, we are checking whether we already have one available copy. If we do not have any such copy, we’ll create it; otherwise, we’ll simply reuse the existing copy.

UML Class Diagram

9781484218013_unFig03-01.jpg

Package Explorer view

High-level structure of the parts of the program is as follows:

9781484218013_unFig03-02.jpg

Implementation

package singleton.pattern.demo;
class MakeACaptain
{
        private static MakeACaptain _captain;
        //We make the constructor private to prevent the use of "new"
        private MakeACaptain() { }

    public static MakeACaptain getCaptain()
    {

                 // Lazy initialization
                 if (_captain == null)
                 { _captain = new MakeACaptain();
                    System.out.println("New Captain selected for our team");
                 }
                 else
                 {
                         System.out.print("You already have a Captain for your team.");
                         System.out.println("Send him for the toss.");
                 }
                 return _captain;

          }
  }
class SingletonPatternEx
{
        public static void main(String[] args)
    {
                System.out.println("***Singleton Pattern Demo*** ");
                System.out.println("Trying to make a captain for our team");
                MakeACaptain c1 = MakeACaptain.getCaptain();
                System.out.println("Trying to make another captain for our team");
                MakeACaptain c2 = MakeACaptain.getCaptain();
                        if (c1 == c2)
                        {
                                System.out.println("c1 and c2 are same instance");
                        }
                }
}

Output

9781484218013_unFig03-03.jpg

Note

Why in the code have we used the term “Lazy initialization”?

Because, the singleton instance will not be created until the } getCaptain() method is called here.

Point out one improvement area in the above implementation?

The above implementation is not thread safe. So, there may be a situation when two or more threads come into picture and they create more than one object of the singleton class.

So what do we need to do to incorporate thread safety in the above implementation?

There are many discussions on this topic. People came up with their own solutions. But there are always pros and cons. I want to highlight some of them here:

Case (i): Use of “synchronized” keyword:

public static synchronized MakeACaptain getCaptain()
{
  //our code
}

With the above solution we need to pay for the performance cost associated with this synchronization method.

Case (ii): There is another method} called “Eager initialization” (opposite of “Lazy initialization” mentioned in our original code) to achieve thread safety.

class MakeACaptain
      {
          //Early initialization
          private static MakeACaptain _captain = new MakeACaptain();
          //We make the constructor private to prevent the use of "new"
          private MakeACaptain() { }

          // Global point of access //MakeACaptain.getCaptain() is a public static //method
          public static MakeACaptain getCaptain()
          {
              return _captain;
          }
      }

In the above solution an object of the singleton class is always instantiated.

Case (iii): To deal with this kind of situation, Bill Pugh came up with a different approach:

class MakeACaptain
{
        private static MakeACaptain _captain;
        private MakeACaptain() { }

      //Bill Pugh solution
      private static class SingletonHelper{
      //Nested class is referenced after getCaptain() is called

          private static final MakeACaptain _captain = new MakeACaptain();
      }

      public static MakeACaptain getCaptain()
      {
          return SingletonHelper._captain;
      }

  }

This method does not need to use the synchronization technique and eager initialization. It is regarded as the standard method to implement singletons in Java.

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

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