Click here to Skip to main content
15,906,341 members
Articles / All Topics

Singleton

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
6 Feb 2010CPOL2 min read 7.6K   3  
Singleton

Imagine that you need some global logging system in your application. You need to be able to log your messages to some file at any point of your application, but you also need to numerate your messages. How can you accomplish this?

Singleton

Class which is represented below is an example of Singleton Design Pattern.

C#
public class LoggerSingleton {

    private LoggerSingleton(){}
    
    private int _logCount = 0;
    private static LoggerSingleton _loggerSingletonInstance = new LoggerSingleton();
    
    public static LoggerSingleton GetInstance(){
    return _loggerSingletonInstance;
    }
    
    public void Log(String message){
    System.out.println(_logCount + ": " + message);
    _logCount++;
    }
}

You are going to start executing your doHardWork method and you want to log that you just started doing hard work and what occurred doing it. So your functional system could look like below:

C#
public static void doHardWork() {
    LoggerSingleton logger = LoggerSingleton.GetInstance();
    HardProcessor processor = new HardProcessor(1);

    logger.Log("Hard work started...");

    processor.processTo(5);

    logger.Log("Hard work finished...");
}

As you see, there is some class called HardProcessor. We should not really care how it works. All we should care about is that when it is created, we want to log this and also we want to log when it is done with some calculations.

C#
public class HardProcessor {
    
    private int _start;

    public HardProcessor(int start){
    _start = start;
    LoggerSingleton.GetInstance().Log("Processor just created.");
    }
    
    public int processTo(int end){
    int sum = 0;
    for(int i = _start; i <= end; ++i){
       sum += i; 
    }
    LoggerSingleton.GetInstance().Log("Processor just calculated some value: " + sum);
    return sum;
    }   
}

Here is the output of your program:

0: Processor just created.
1: Hard work started...
2: Processor just calculated some value: 15
3: Hard work finished...

I wrote this example when I was in the train with my friend. And I showed him my story and he said that I wrote Monostate. -"Me? Where?". We took a look at my code and the only one variable I was using _logCount was static initially.

What is the Difference between Singleton and Monostate?

Singleton is way to ensure that class has only one instance. Monostage if you see globally on it does the same as GOF Singleton. All variables of it are static and this allows you to have many instances of monostate, but of course, they will share the same data. This also resolves many issues with multiconcurrency usage of Singleton.

Let's take a look at my example once again. Could be that your logger is not so trivial, maybe on start of application, you want to open some log file and get the latest message number, so logger will continue to write to file with correct numbers. Also, your application is not so trivial. Maybe you are accessing your Singleton not only from just different places in your code but from different threads. But since your constructor interacts with IO, it takes time to construct your instance. So GetInstance() in reality in such a situation could create TWO instances. Not really good for your application. For our luck, there are many ways to resolve this issue. Commonly, we use Double-Checked Locking.

C#
public class ThreadSafeLoggerSingleton {

    private ThreadSafeLoggerSingleton() {
       //reads data from some file and gets latest number of message
       //_logCount = got value here...
    }

    private int _logCount = 0;

    private static ThreadSafeLoggerSingleton _loggerInstance;

    public static ThreadSafeLoggerSingleton GetInstance(){
    if (_loggerInstance == null) {
          synchronized (ThreadSafeLoggerSingleton.class) {
            if (_loggerInstance == null)
                _loggerInstance = new ThreadSafeLoggerSingleton();
          }
        }
        return _loggerInstance;
    }

    public void Log(String message) {
        System.out.println(_logCount + ": " + message);
        _logCount++;
    }
}

The way is not single and not all implementations of the DCL work! Read this good article on this: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Also, as you see in method Log, I'm using variable of my class and doing an operation on it, which is almost atomary. But if operations will be more complex, you will need synchronization there as well.

Go to: My Design Patterns Table

This article was originally posted at http://andriybuday.blogspot.com/feeds/posts/default

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer SoftServe
Ukraine Ukraine
I'm very pragmatic and self-improving person. My goal is to become successful community developer.
I'm young and love learning, these are precondition to my success.

Currently I'm working in dedicated Ukrainian outsourcing company SoftServe as .NET developer on enterprise project. In everyday work I'm interacting with lot of technologies which are close to .NET (NHibernate, UnitTesting, StructureMap, WCF, Win/WebServices, and so on...)

Feel free to contact me.

Comments and Discussions

 
-- There are no messages in this forum --