views:

167

answers:

6

This might sound like a weird idea and I haven't thought it through properly yet.

Say you have an application that ends up requiring a certain number of singletons to do some I/O for example. You could write one singleton and basically reproduce the code as many times as needed.

However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind. What would be a solution to make multiple somethings that could each act as a singleton.

P.S: This is for a project where a framework such as Spring can't be used.

+1  A: 

How about passing a parameter to the function that creates the singleton (for example, it's name or specialization), that knows to create a singleton for each unique parameter?

Amir Rachum
That would ideal. This goes along with the suggestion of using a Factory pattern.
James P.
+3  A: 

You could introduce an abstraction like this:

public abstract class Singleton<T> {
  private T object;

  public synchronized T get() {
    if (object == null) {
      object = create();
    }
    return object;
  }

  protected abstract T create();
}

Then for each singleton, you just need to write this:

public final Singleton<Database> database = new Singleton<Database>() {
  @Override
  protected Database create() {
    // connect to the database, return the Database instance
  }
};

public final Singleton<LogCluster> logs = new Singleton<LogCluster>() {
  ...

Then you can use the singletons by writing database.get(). If the singleton hasn't been created, it is created and initialized.

The reason people probably don't do this, and prefer to just repeatedly write something like this:

private Database database;

public synchronized Database getDatabase() {
  if (database == null) {
    // connect to the database, assign the database field
  }
  return database;
}

private LogCluster logs;

public synchronized LogCluster getLogs() {
  ...

Is because in the end it is only one more line of code for each singleton, and the chance of getting the initialize-singleton pattern wrong is pretty low.

Dominic Cooney
This is... scary. Connecting the DB during construction of a Singleton?
BalusC
That's over-complication to the max right there.
Gnarly
@Gnarly I'm basically arguing that this is why you *don't* do this. Personally I prefer Guice (although that can be complicated in its own way.)
Dominic Cooney
+2  A: 

There does exist a multiton pattern. Regardless, I am 60% certain that the real solution to the original problem is a RDBMS.

emory
+1 for Multiton Pattern
Tim Bender
I hadn't heard of this pattern before and it does sound similar to what Spring must do internally. Here's a link for future reference: http://j2eeblogger.blogspot.com/2007/10/singleton-vs-multiton-synchronization.html
James P.
A: 

I know you asked about Java, but here is a solution in PHP as an example:

abstract class Singleton
{
    protected function __construct()
    {
    }

    final public static function getInstance()
    {
        static $instances = array();

        $calledClass = get_called_class();

        if (!isset($instances[$calledClass]))
        {
            $instances[$calledClass] = new $calledClass();
        }

        return $instances[$calledClass];
    }

    final private function __clone()
    {
    }
}

Then you just write:

class Database extends Singleton {}
Coronatus
-1 - This approach does not work for Java. Static methods are not inherited, so there's no equivalent to `get_called_class`.
Stephen C
This is correct but since I'm interested in PHP too I'll upvote you since you took the trouble of posting a code sample.
James P.
+3  A: 

However, as programmers we're supposed to come up with inventive solutions that avoid redundancy or repetition of any kind.

That is not correct. As programmers, we are supposed to come up with solutions that meet the following criteria:

  • meet the functional requirements; e.g. perform as required without bugs,
  • are delivered within the mandated timeframe,
  • are maintainable; e.g. the next developer can read and modify the code,
  • performs fast enough for the task in hand, and
  • can be reused in future tasks.

(These criteria are roughly ordered by decreasing priority, though different contexts may dictate a different order.)

Inventiveness is NOT a requirement, and "avoid[ing] redundancy or repetition of any kind" is not either. In fact both of these can be distinctly harmful ... if the programmer ignores the real criteria.

Bringing this back to your question. You should only be looking for alternative ways to do singletons if it is going to actually make the code more maintainable. Complicated "inventive" solutions may well return to bite you (or the people who have to maintain your code in the future), even if they succeed in reducing the number of lines of repeated code.

And as others have pointed out (e.g. @BalusC), current thinking is that the singleton pattern should be avoided in a lot of classes of application.

Stephen C
I've seen a lot of typos of my name before, but not this one yet :)
BalusC
@BalusC - Fixed. Sorry.
Stephen C
On one hand, if this answered the question, I'd up vote it. On the other hand, it seems like an argumentative response to an unnecessary comment in the original post (though the OPs flawed thinking may very well be the root cause of this question).
Tim Bender
@Tim Bender - if someone is waving a loaded gun, it is better to get him to put the gun down rather than offer him 1) a bandaid for his foot, or 2) shooting lessons. IMO, the OP's apparent obsession with avoiding redundancy is like a loaded gun. (OK, maybe a beebee gun ...)
Stephen C
@Stephen C, I've seen the end result of a similar situation in which a programmer was obsessed with generics. Your analogy breaks down in your belief that you can get him to put down the gun. At least with shooting lessons the OP won't do as much collateral damage.
Tim Bender
@Tim Bender - but you should at least *try* to get him to put the gun down. Or, in this case, as I have tried to do, correct the OP's unhealthy obsession with eliminating repetitious code.
Stephen C
@Stephen C: Maybe I do have an obsession ;) . You're right about the criteria. The question popped up as I was beginning to think it would be tedious to reproduce more or less the same structure. I'm open to suggestions as to any alternatives.
James P.
+2  A: 

@BalusC is right, but I will say it more strongly, Singletons are evil in all contexts. Webapps, desktop apps, etc. Just don't do it.

All a singleton is in reality is a global wad of data. Global data is bad. It makes proper unit testing impossible. It makes tracing down weird bugs much, much harder.

The Gang of Four book is flat out wrong here. Or at least obsolete by a decade and a half.

If you want only one instance, have a factory that makes only one. Its easy.

fishtoprecords