1

I heard that static (in the Java sense, basically a static method is called on the class itself and not on an instance) is not True OOP. However, how would the Singleton pattern be implemented in such a language. I thought of having an FooGetter class, and calling a getFoo() method on an instance of it, but how will the FooGetter store the instance of Foo without static variables?

  • 4
    Who cares if it's not "True OOP", whatever that is. Does your software get sent to some sort of purgatory if it taints itself with some mixed-paradigm sins? – whatsisname Mar 23 '18 at 4:09
  • @whatsisname I am just thinking theoretically – vikarjramun Mar 23 '18 at 13:08
  • 1
    If a static variable is "not true OOP" then a Singleton is "not true OOP" either... – Sean Burton Mar 23 '18 at 15:34
  • Show me a useful "true OP" program that does not use a form of stateful/static/global data. I will make it really easy - start with "Hello World" – mattnz Jun 14 at 2:01
4

A singleton pattern implementation such as:

public final class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

can be replaced with dependency injection. Simply construct the object once, in the static method main, and pass it to everything that needs it.

public static void main(){
    Date applicationStart = new Date();

    Uptime uptime = new Uptime(applicationStart);
    Performance performance = new Performance(applicationStart);

    //...
}

Here two objects that both need to know the application start and do not want to see the Date constructed twice are both given references to the same single object. By responsibly passing around a reference rather than fearfully preventing construction all requirements are met. This approach allows for far more flexibility since the users of the singleton are not required to know how to find it.

The drawback with this approach is it doesn't support lazy initialization.

However, this is only needed if construction of the object is expensive. Many designs avoid the problem by forbidding constructors from doing work besides validation and storing of instance variables. Generally neither is expensive enough to justify lazy initialization. The size of the object can also be a reason for lazy initialization. Good designs tend to avoid large objects. Initializing a resource and modeling it's availability with the creation of an object also may provide a reason to use lazy initialization. How much sense that makes may depend on language due to object lifetime semantics.

Lazy initialization doesn't require the singleton pattern in any case. DI combined with an single abstract factory object that also caches the object it constructs when called will also satisfy a lazy initialization requirement without hard coding clients to the construction code.

The singleton pattern is largely avoided because it solves problems that good designs don't have in the first place. But when the need arises it still works as well as it ever did. Object oriented or not.

  • How would Dependency Injection by a DI Framework such as Guice or Spring work? – vikarjramun Mar 23 '18 at 2:58
  • @vikarjramun They have the ability to register singletons as well. The big benefit DI frameworks provide is that object construction and behavior code are forced to be separate because they now happen in different languages (e.g. xml & java). You can also keep them seperate without the frameworks if you'll just be a little disciplined. – candied_orange Mar 23 '18 at 3:19
  • "can be replaced with dependency injection. Simply construct the object once, in the static method main, and pass it to everything that needs it." I think you're being a bit fast and loose here. A key aspect of the singleton pattern is that it is able to enforce the one instance rule, or have the compiler enforce it. Switching to the honor system to not instantiate additional instances doesn't really count. – whatsisname Mar 23 '18 at 4:07
  • 1
    @whatsisname: In Objective-C, nobody (except absolute noobs) enforces actively that only one instance of a class can exist. If a programmer manages to create a second instance, they deserve every bit of trouble they get. – gnasher729 Apr 7 '18 at 10:08
  • 1
    @whatsisname you're describing the GoF singleton PATTERN. The word Singleton just means there is only one object instance. It doesn't dictate how you achieve it. That's an implementation detail. Don't confuse a requirement with an implementation. – candied_orange Apr 10 '18 at 3:07
0

A version entirely without static; concurrency safe.

public enum Singleton {
    INSTANCE;

    public final AtomicLong counter;

    Singleton() {
        counter = new AtomicLong(System.currentMillis());
    }

    /**
     * For unit testing.
     * @param value.
     */
    void setCounter(long value) {
        counter.set(value);
    }
}

And concurrency safe (guaranteed by enum), and a final class.

Static is nothing bad as such: enums are static. Singletons are static in scope. Statics are global variables, could cause memory leaks, are hard to test, add to start up overhead.

  • This is a kind of old question but thanks for your answer. While I guess this works, it kind of shirks the whole True OOP idea. It's technically correct though so... – vikarjramun Jun 12 at 10:38
  • @vikarjramun yes I agree; I just did not want to leave an answer with concurrency unsafe initialisation stand alone. With OOP one early reaches the need of container managed beans with different scops (session, ...) and the application scope indeed is a kind of singleton. – Joop Eggen Jun 12 at 11:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.