Singleton Design Pattern vs. Static Packages

In lecture 13, a question was asked about the difference between using the Singleton design pattern and making use of a class consisting entirely of static methods and member variables. In other words, what is the difference between this:

                import java.util.Date;
                
                public class Singleton {
                    private static Singleton instance;
                    
                    private Date d;
                    
                    private Singleton() {
                        d = new Date();
                    }
                    
                    public synchronized static Singleton instance() {
                        if (instance == null) {
                            instance = new Singleton();
                        }
                        return instance;
                    }
                    
                    public Date getDate() {
                        return d;
                    }
                }
            

and this:

                public class Singleton {
                
                    private static Date d = new Date();
                    
                    public static Date getDate() {
                        return d;
                    }
                }
            

Both are functionally equivalent, in that only one instance of the date value is ever created and you can retrieve that one instance. But, there are a few differences that can be highlighted that may push you towards using the Singleton design pattern. To wit:

  1. The first difference is largely conceptual. The static package approach is too similar to procedural based programming. In OO, the modus operandi is objects; and we should stick with objects in our analysis, design, and implementation as much as possible.

  2. The second difference is one I mentioned in class: its a "shorter hop" to the variation of the singleton pattern that allows n instances of an object to be created, with:

    0 < n < upper bound

    when you start with the singleton pattern than with the static package approach.

  3. The third difference is that if you wanted to allow the creation of several subclasses of the original Singleton class and then choose at run-time which subclass was going to be instantiated and then allow only one of those instances to be created, you would need to start with the singleton pattern.

  4. Finally, a fourth difference was pointed out to me by Ryan G. Dejana, a CAETE student who works for IBM. Ryan points out that static methods are not polymorphic. So, if you tried to simulate this design pattern with the static package approach and had subclasses of the original "Singleton" class, you might run into unexpected behavior. The following three classes demonstrate the problem:

                        public class Test {
                        
                            public static String getMessage(){
                                return getString();
                            }
                        
                            protected static String getString(){
                                return "Hello from Test";
                            }
                        
                        }
    
                        public class Test2 extends Test {
                            protected static String getString(){
                                return "Hello from Test2";
                            }
                        }
    
                        public class Main {
                        
                            public static void main(String[] args) {
                                System.out.println(Test2.getMessage());
                            }
                        
                        }
                    

    The output of Main is "Hello from Test" and not "Hello From Test2"

I hope this information is useful! Feel free to send me e-mail if you want to add to this discussion. I'll be glad to post updates.