Most of the time singletons is not necessary since a single instance of the class can be created at start up and then passed to objects that need it. This has the downside that you have to pass the used-to-be-singleton-object to a class A just because it creates a class B which needs the used-to-be-singleton-object. Yuck!
Seriously, designing software properly takes enough time as it is, I don't need more tedious details to worry about. Just make it work! Just give class B an object that provides it with the services it needs.
So, what's the alternative then (hint: title)? Dynamic scoping in Java, of course!
I think a disclamer is in order: I don't consider dynamic scoping to be the best solution to the problem described above. If it is possible redesigning the code such that its maintanability is improved without usins dynamic scoping, then that is much better. If this is not possible, however, then dynamic scoping may be the solution you seek. Now, let's discuss how to implement this scoping business.
I would like a way to express "from now on, every time I ask for a class A, give me the instance of that class that is on the top of the stack", where stack means the stack where all the variable in the dynamic scope is stored. Also, I would like to express that an object is pushed to the dynamic scoping stack like this:
// place 'object' in the dynamic scope
scope (object) {
// code calling code calling code calling code using 'object'.
}
// 'object' is not in the dynamic scope anymore
where scope is a new keyword I made up for the sake of the discussion. Allrighty then, how can that be done i simple Java? Simple answer: it can't, Java isn't close to expressive enough to let the programmer define new control structures and keywords. We have to do like this instead:
new Scope(object) { {
// code calling code calling code calling code using 'object'.
} }.done();
Neat! But wait a minute... how do we get an object that is placed in the dynamic scope? It easy, like this:
ClassOfObject object = Scope.of(ClassOfObject.class);
As you can see there is no way to say "I want that (points with finger) instance of ClassOfObject", you can only say "yeah, whatever, give me something I can do X, Y, and Z with". This may appear to be a limitiation, but its actually a feature: it keeps encapsulation and its overridable (it's possible to push another instance of ClassOfObject to the dynamic scoping stack, which then will be returned whenever someone (inside that scope) calls Scope.of(ClassOfObject.class)).
And this is how the Scope class is implemented, and here are some simple test-cases.
The Scope class is, of course, not thread-safe, because it would be a mistake from my side to even try accomplish thread-safety...
2 comments:
Your method of writing the inner code to run is clever, and for a moment I wondered how it worked. But then I realized it is unsafe. If the inner code throws an exception, you fail to unwind the dynamic scope. Nice anyway. :-)
You are right, if the code inside the "scope" throws an exception then the scope isn't cleaned up. I didn't think about that...
Can you come up with an implementation that handles that? If Java had proper destructors, then maybe it would be possible -- but without them I don't see how it is possible.
Post a Comment