14 November 2012

Singleton Design Pattern

Ensures a class has only one instance and provides a global point of access to it.

My first impressions on Singleton’s were that they are a simple pattern and didn’t seem particularly interesting. It didn’t take long for me to become disabused of that notion. Surprisingly there is something of a controversy when it comes to singleton’s, which can quickly result in brain fatigue. The various arguments for and against the Singleton pattern are rarely accompanied by code or even diagrams to illustrate the points being made.

One common complaint being that it results in tightly coupled code. I found this assertion somewhat baffling, but going back to some fundamentals of programming, it began to make more sense. That is what we will explore here in this article. Along the way we will discuss tightly coupled code and throw in a little Rock and Roll!

Continuing our Role Playing Game theme will give us our example business story/rule to play with. In this case rules are the subject matter! For the game to be fun, everyone and everything must be using the same rules. So it makes sense for there to be one and only one set of rules which everyone and everything must use. This sounds like a great place for a singleton!

Let us write a basic singleton pattern in Java as shown below.

RuleSystem.java
package singleton;

public class RuleSystem {

  private static volatile RuleSystem ruleSystem;

  private RuleSystem() {
    
  }
  
  public static synchronized RuleSystem getInstance() {
    if (ruleSystem == null) {
      ruleSystem = new RuleSystem();
    }
    return ruleSystem;
  }

}

This class uses static methods and static attributes because our goal is to have one and only one instance of the RuleSystem class. The method is “synchronized” to avoid assigning one object to “ruleSystem”, followed by another object, in a multiple thread scenario.

If you Google or search on StackOverflow you will find discussions on the benefits and detriments of the Singleton Design Pattern. The most predominant one being that it results in tightly coupled code. I faced two obstacles in understanding their point. The first was that they are discussing a singleton, as defined at the beginning of this article, exactly, without deviation. We will discuss this more in Part 2 of Singletons. The second was in understanding what “tightly coupled” and “loosely coupled” mean.

...Just Hold On Loosely But don't let go. If you cling to tightly. You're gonna lose control...

In addition to being a pretty good song, Hang on Loosely, is part of the core principles behind the design patterns. Loosely coupled code requires less maintenance than tightly coupled code. How do we recognize tightly coupled code and will it really increase my workload? A good question and one we should look into.

When two objects are loosely coupled, they can interact, but have very little knowledge of each other.

Well we have a definition now, but what does it mean when you are writing code? Well I still don’t know either! So let’s go an see what Wikipedia has to say. Wow! While starting to make sense, things have gotten more complicated. The most obvious problem seems to be that singleton’s are a module that other modules depend on. This can make testing more difficult. Tightly coupled code would also be a result. Since it is static it is acting on a global scope and has all the problems and benefits associated with global variables. Which is a whole article itself!

We should write code to illustrate the tight coupling problem. Using Java we will create a TightCouple and a LooseCouple class. Using a Coupling class we will show the difference between the two. These three files are shown below.

TightCouple.java
package coupling;

import java.util.ArrayList;

public class TightCouple {
  private ArrayList myList;

  public ArrayList getMyList() {
    return myList;
  }

  public void setMyList(ArrayList myList) {
    this.myList = myList;
  }    
}
LooseCouple.java
package coupling;

import java.util.*;

public class LooseCouple {
  private List myList;

  public List getMyList() {
    return myList;
  }

  public void setMyList(List myList) {
    this.myList = myList;
  }    
}
Coupling.java
package coupling;
import java.util.*;

public class Coupling {
  
  
  public static void main(String[] args) {
    TightCouple tight = new TightCouple();
    tight.setMyList(new ArrayList());
    
    LooseCouple loose = new LooseCouple();
    loose.setMyList(new Vector());
    loose.setMyList(new Stack());
    loose.setMyList(new ArrayList());
  }
}

In the TightCouple class we specified myList as an ArrayList class. This means that we can only assign classes of type ArrayList, or possibly a subclass of ArrayList, to the myList variable. The LooseCouple class, on the other hand, defines myList as a List interface. This means we can assign any class to the myList variable as long as it implements the List interface. As we can see in the Coupling class we are able to set myList to a Vector, Stack and ArrayList. This gives us flexibility, which is used in the design patterns we have been discussing.

Tightly coupled code can increase your workload. I recently built a few classes that had methods that took HashMap as a parameter. I later decided that in some cases I really needed LinkedHashMap to be passed into the methods. The result was that I would have to modify each of the classes to allow LinkedHashMap to be passed to the classes’ methods. We know the right way is to define the method parameter as a Map interface so that any class implementing it could be used. If I had done this the first time, I wouldn’t have needed to modify the existing classes when I switched to using LinkedHashMap.

The singleton code above results in tightly coupled code because it returns an object of the RuleSystem class. We could fix this by returning an interface which would allow us to return any number of objects as long as they implement the appropriate interface. This would only work if we thought well enough ahead to define an appropriate interface. Keep in mind that just using an interface without forethought will limit its effectiveness.

Java and C# programmers sometimes take the advice to "program to an interface" literally, as the interface is an actual construct in those languages.

This only scratches the surface of Tightly vs Loosely coupled code. In Part 2, of this article, we will explore how we can modify the Singleton pattern to eliminate some of the problems we have discussed.


Less Is More ~ Older posts are available in the archive.