This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
Hi 1) Methods that are static cannot be used to implement an interface. Hence we lose a great deal of the power of Java's interface entity. 2) All references to the singleton must be hard-coded with the name of the class. Hence there is no meaningful way to override the static methods. In other words, all static methods may as well be final.
The main difference is extensibility. Because static methods are tied to a particular class, there's no way to use virtual method calls. (This is the reason that, as the last poster correctly stated, you can't implement an interface with static methods--by definition, all calls to interface methods must be delegated to an implementing class, and hence are virtual. Incidentally, the only non-virtual methods in Java besides static are those that are marked final.)
The purpose of a design pattern like Singleton is to address a problem that occurs in many different situations generally, and that's not usually possible unless you provide for extensibility. Since static methods cannot be overridden, they are not extensible. Singleton avoids this by keeping the instance of the class as a static member (and providing access to it with a static method), but the class itself is comprised of instance methods:
So the question is, what good is extensibility in this case? Even if you write a class Bar the extends Foo, Foo.getInstance() will always and forever return an object of class Foo (instance is a "new Foo()", not a "new Bar()").
In that case, you'd want to use the Abstract Factory pattern in combination with these two Singletons (Foo and Bar) to provide correct Singleton to other classes. In fact, usually when using Abstract Factory, you'd abstract the interface of the class returned by an AF so callers wouldn't know the class of the object they're using at all (they work with the interface, so they only know the type).