I'm looking for a piece of code which behaves a bit like a singleton but isn't (because singleton's are bad :) What I'm looking for must meet these goals:
- Thread safe
- Simple (Understand & use, i.e. few lines of code. Library calls are OK)
- Fast
- Not a singleton; for tests, it must be possible to overwrite the value (and reset it after the test).
- Local (all necessary information must be in one place)
- Lazy (run only when the value is actually needed).
- Run once (code on RHS must be executed once and only once)
Example code:
private int i = runOnce(5); // Set i to 5
// Create the connection once and cache the result
private Connection db = runOnce(createDBConnection("DB_NAME"));
public void m() {
String greet = runOnce("World");
System.out.println("Hello, "+greet+"!");
}
Note that the fields are not static; only the RHS (right hand side) of the expression is ... well "static" to some degree. A test should be able to inject new values for i
and greet
temporarily.
Also note that this piece of code outlines how I intend to use this new code. Feel free to replace runOnce() with anything or move it to some other place (the constructor, maybe, or an init() method or a getter). But the less LOC, the better.
Some background information:
I'm not looking for Spring, I'm looking for a piece of code which can be used for the most common case: You need to implement an interface and there won't ever be a second implementation except for tests where you want to pass in mock objects. Also, Spring fails #2, #3 and #5: You need to learn the config language, you must set up the app context somewhere, it needs an XML parser and it's not local (information is spread all over the place).
A global config object or factory doesn't meet the bill because of #5.
static final
is out because of #4 (can't change final). static
smells because of classloader issues but you'll probably need it inside runOnce()
. I'd just prefer to be able to avoid it in the LHS of the expression.
One possible solution might be to use ehcache with a default setup which would return the same object. Since I can put things in the cache, this would also allow to override the value at any time. But maybe there is a more compact/simple solution than ehcache (which again needs an XML config file, etc).
[EDIT] I'm wondering why so many people downvote this. It's a valid question and the use case is pretty common (at least in my code). So if you don't understand the question (or the reason behind it) or if you have no answer or you don't care, why downvote? :/
[EDIT2] If you look at the app context of Spring, you'll find that more than 99% of all beans have just a single implementation. You could have more but in practice, you simply don't. So instead of separating interface, implementation and configuration, I'm looking at something which has only an implementation (in the most simple case), a current() method and one or two lines of clever code to initialize the result for current() once (when it is called for the first time) but at the same times allows to override the result (thread safe, if possible). Think of it as an atomic "if(o==null) o = new O(); return o" where you can override the o. Maybe an AtomicRunOnceReference class is the solution.
Right now, I just feel that what we all have and use daily is not the optimum, that there is a baffling solution which will make us all slap our heads and say "that's it". Just as we felt when Spring came around a few years ago and we realized where all our singleton problems came from and how to solve them.