Oct 4, 2010

Static class vs Singleton

Design pattern question is often asked in interview for developer. In an interview, I was asked to describe one design pattern that I am familiar, except singleton. Maybe the interviewer think that Singleton is too easy to answer. Yes singleton is a very simple, a sample is as follow.


class Program
{
 static void Main(string[] args)
 {
  Printer.Instance().Print();
 }
}

class Printer
{
 static Printer _printer;

 public static Printer Instance()
 {
  if (_printer == null)
  {
   _printer = new Printer();
  }
  return _printer;
 }

 protected Printer()
 { }

 public void Print()
 {
  Console.WriteLine("printing...");
 }
}

Although Singleton pattern is simple, it can be also used to test applicant's understanding of object. Let's say, if someone writes the following code some code argues that design pattern is useless, structured procedure is better. In some case, structured procedure is just as good. Can you write some code demonstrate in what scenario Singleton solve problem that static method cannot solve? (Don't think of mullti-threading, it is not an issue here.)


class Program
{
 static void Main(string[] args)
 {
  Printer.Print();
 }
}

static class Printer
{
 public static void Print()
 {
  Console.WriteLine("printing...");
 }
}


My answer

Although two solutions look similar, but it reflects different thinking. One of book affect me most in my programming career is Object Thinking. In this book, it says


The essential thinking difference is easily stated: “Think like an object.” Of course, this statement gets its real meaning by contrast with the typical approach to software development: “Think like a computer.” Thinking like a computer is the prevailing mental habit of traditional developers.

The singleton solution is reflection of "think like an object". When you think like an object, you are also an object, the other objects will be your buddies. You will interact with printer buddy by his interface. As long as your buddy expose the your printer interface, you know how to communicate with him. It doesn't matter who your buddy is, what matters is you know what kind of service your buddy provide you. You scenario will be, I see a Printer guy, he is the only printer guy, I don't care who he is, but he says he can print, so I ask him, "Print, please". If you think this way, you can write the following code. This is fundamental feature of object-oriented technique, polymorphism.


class Program
{
 static void Main(string[] args)
 {
  Printer.Instance().Print();
 }
}

abstract class Printer
{
 static Printer _printer;

 public static Printer Instance()
 {
  if (_printer == null)
  {
    Type pritnerType = GetPrinterTypeFromConfiguration();
    _printer = Activator.CreateInstance(printerType) as Printer;
  }
  return _printer;
 }
  public abstract void Print();
}

class LaserJetPrinter : Printer
{
   public virtual void Print()
   {
      Console.WriteLine("hhhhhhhhhhhh");
    }
}

class InkJetPrinter : Printer
{
   public virtual void Print()
   {
     Console.WriteLine("kakaka");
    }

}

If you think like a machine, your mindset will be like, I am the master of the printer, I want feed it with some instructions. Ok, I have menu of the machine, one of instruction is "print", let me feed it, and it prints. If you think like this, you will write the static method like above. This is not necessary bad practice, in fact it is even the best practice(please check CA1822: Mark members as static, if you never want to have differently print behavior. Until then You have much less flexibility, and OO is your friend.