-3

When this question has been asked before on StackOverflow in 2011 and 2015, all answers as of now suggest to use a Singleton.

But that’s not right.

Singletons are defined by the Gang of Four to mean two things: 1) Ensure a single instance 2) Accessible everywhere

I do not want accessibility everywhere. There are many posts as to the havoc globally mutable state can cause. My proposed solution is as follows:

public class MyClass
{
    private static bool instanceCreated = false;

    public static MyClass Create()
    {
        if (instanceCreated) 
        {
            throw new Exception("Already created one instance of MyClass.");
        }

        MyClass myClass = new MyClass();
        instanceCreated = true;

        return myClass;
    }

    private MyClass()
    {
    }
}

For context, as per comment: I'm trying to only allow one instance because I thought that was good practice... hence why people use Singleton. I am designing an adapter for my database, and do not want it modified from just anywhere.

My question:

Did I stumble across a new and innovative technique? Or is this well-documented, perhaps even a design pattern or its own? What other resources should I, and future searchers of this question, look at to understand how to ensure single instance of class WITHOUT the singleton pattern?

  • Can someone comment as to why this got 3 downvotes in under 10 min? – John Doe Dec 20 '19 at 21:52
  • 2
    Your code lacks thread safety, but I guess that's a different issue... I think you need to think first about the issue you are trying to solve. Singleton is a well known, understood and tested solution, with its pros and cons (as everything else). If you don't want a mutable object, perhaps what you want is an enum? You should provide a little more context. – Juan Carlos Eduardo Romaina Ac Dec 20 '19 at 21:53
  • Thanks, edited. – John Doe Dec 20 '19 at 21:58
  • 1
    Globally mutable state is good if you want globally mutable state, and changes cannot be made without notifying interested parties. You can achieve that by using a singleton. – gnasher729 Dec 22 '19 at 18:34
  • 1
    Suppose a program uses two third-party libraries, both of which call your public method Create; how is the author of that program supposed to know that they cannot use both libraries in the same program? Which ever library goes second will always crash, and cannot obtain the instance it needs. – Eric Lippert Jan 9 at 20:14
6

What you have written is also a singleton. Just that you throw an error when accessing it a second time. So it lacks the gloabal access to the instance, but only from the second access.

So you did not really reinvent the wheel with this. Sorry :)

In general i consider the singleton as a "outdated" pattern. Also it handles 2 things at the same time, which violates the single responsibility (for change) principle. All its benefits, and many more, can be achieved using a Dependency Injection Container as the essential component of the IoC Pattern.

With the container, the lifetime-property of your object is no longer baked into you class, but is managed by an external entity, and can be adopted to many usecases without ever touching the code of your class.

1

Yes it seems fairly innovative to me. Let's critque it.

So I'm thinking we already have almost-singletons where we use DI containers with a single instance registration.

This gives scope to the instance, which is what you want.

I think the main problem with your implementation is that it throws a runtime error if you call create twice

The benefit of a singleton is that it compile time enforces the single instance. A run time check just crashes the program if you attempt to make two instances.

Plus presumably you hold a reference to the object from the first time you call it. How is a run time check any better than simply calling the constructor once at the start of your program?

If you have a container class then you can scope your single instance to the container rather than globally and also return the same instance if create is called a second time (per container) rather than throwing an error.

  • You are right that I hold a reference to the object, so effectively limit scope to anything in that container with dependency injection. So you are right that it is the same as just calling it once at the start of my application. I guess I created my solution because I wanted to ensure a DI (dependency injection) container with single instance registration. – John Doe Dec 21 '19 at 1:47
  • Am I reading your answer correctly when I assume: DI containers still have the problem that, yes, another container elsewhere in the application COULD instantiate the same object, but this is a rather trivial problem with which I should not concern myself? – John Doe Dec 21 '19 at 1:48
  • 1
    @JohnDoe Just saying: You CAN'T instantiate the same object, you CAN instantiate a second instance of the same class. It will be a different object. – gnasher729 Dec 22 '19 at 15:18
  • 1
    Yes, but that is the nature of not being global. With your method you have a global variable which is hard to access. With the container you get a single instance scoped to a container – Ewan Dec 22 '19 at 16:57
1

What I would advise today: The "Singleton" pattern was a nice idea when they wrote it down for the first time, but it is outdated.

You don't really want a singleton. What you want (in many cases) is a single object that you can refer to for performing a specific task, that you can access using a simple, well-defined mechanism, that is put into existence the first time it is accessed that way, and which will stay in existence as long as the application is running.

At many times having a class with a single instance solves that requirement. However, in my world nobody tries preventing more than one instance to be created - if you do that as a developer, it's your own fault, shame on you. And I have seen code using two different objects for two different specific tasks, both elements of the same class. Obviously that means you can't assume there's only one instance; data that belongs to an instance must be stored in the instance and not in the class (which is a good idea anyway in case you figure out you need more than one instance of your "Singleton").

These four authors (not the "Gang of Four", that's a group of Chinese counter-revolutionary politicians in the 1960's to 1970's) also specified a specific way how you ought to access the Singleton instance - by calling a class method of the Singleton class. That's not generally accepted as a good method to do this anymore.

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.