> What's wrong with this approach:
>
[quoted text clipped - 12 lines]
>
> public T get() throws InterruptedException {
Declaring InterruptedException you doom users to handle it every time
they access you singleton...
it will be quite inconvenient..
> try {
> return instance == null ? instance = factory.get() :
> instance;
> } catch (InterruptedException e) {
> throw e;
what's the point rethorwing this exception?
> } catch (ExecutionException e) {
> if (e.getCause() instanceof Error) {
[quoted text clipped - 9 lines]
>
> }
Have you tried to run it?
I think it wont work.. FutureTask.run() method must be called, without
it FutureTask.get() won't work!
> This way, you don't have to worry about:
> 1. Thread safety and synchronization (delegated to FutureTask.get())
[quoted text clipped - 24 lines]
> but it can be prematurely cancled by client code, and client code has
> more exception handling to do.
> I have to say though, in my experience, most Singleton patterns can be
> refactored into Dependency Injection with a lot of benefit to the
> overal program design.
Singletons that could be refactored into some sort of IoC are NOT TURE
singletons. Dependency injection is not a way of keeping and managing
objects, it's a way of getting access to them (in sense OOP).
True singletons are unavoidable. Have a look inside implementation of
your favorite IoC container, I'm quite sure you'll find them there:).
Daniel Pitts - 13 Feb 2007 19:42 GMT
> > What's wrong with this approach:
>
[quoted text clipped - 81 lines]
> True singletons are unavoidable. Have a look inside implementation of
> your favorite IoC container, I'm quite sure you'll find them there:).
Improper handling of InterruptedException can lead to severe problems.
If you have an immutable singleton, then this is an acceptible idiom:
class MySingletonHolder {
private final static MySingleton instance = new MySignleton();
public static MySingleton get() {
return instance;
}
}
It is thread-safe and lazily loaded.
Andrey Ryabov - 14 Feb 2007 08:34 GMT
On Feb 13, 10:42 pm, "Daniel Pitts" <googlegrou...@coloraura.com>
wrote:
> > > What's wrong with this approach:
>
[quoted text clipped - 81 lines]
> > True singletons are unavoidable. Have a look inside implementation of
> > your favorite IoC container, I'm quite sure you'll find them there:).
> Improper handling of InterruptedException can lead to severe problems.
I suggest the following way to handle InterruptedException in this
case
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Set interrupt
flag again
throw new RuntimeException(...); // and wrapped
exception.
}
Is something wrong in this approach?
> If you have an immutable singleton, then this is an acceptible idiom:
>
[quoted text clipped - 7 lines]
>
> It is thread-safe and lazily loaded.
Yes.. but I have to be able reinitialize my singleton therefore this
idiom is not acceptable for me.
Daniel Pitts - 14 Feb 2007 19:14 GMT
> On Feb 13, 10:42 pm, "Daniel Pitts" <googlegrou...@coloraura.com>
> wrote:
[quoted text clipped - 114 lines]
> Yes.. but I have to be able reinitialize my singleton therefore this
> idiom is not acceptable for me.
If you have to reinitialize it, then its not a singleton. It is either
a pooled object and/or should be injected.
Also, you need to synchronize if the state can change.
It really sounds to me like you're pushing the square peg called
"Singleton" into a round hole.
Andrey Ryabov - 15 Feb 2007 09:17 GMT
> > Yes.. but I have to be able reinitialize my singleton therefore this
> > idiom is not acceptable for me.
[quoted text clipped - 6 lines]
> It really sounds to me like you're pushing the square peg called
> "Singleton" into a round hole.
Imagine, for example, logging service implemented as singleton. This
service has complex logic and depends on other services: it stores
records to database to remote network server and so on... Then an
application is going to shutdown, it closes connections to database
and remote server but it still uses logging service that is it's turn
uses connections that has already been closed. To avoid this
implementation of logging service can be substituted by another that
don't depends on already stoped services (NullObject or very simple
implementation).
You would suggest me implement logging service that checks wheder or
not application is going to be shotdown. Bug it is possible only is
very rare cases. The number of implementations of singleton services
could not be known, they can substitute each other during program
runtime and should be lazy initialized.
I'm not against the dependency injection but it is not a rescue in
some cases it has a lot of drawbacks, on of them is lack of dynamic
flexibility.
For example:
If service A depends on service B it receive reference to
implementatin of service B (B_impl) during creation. What to do if we
need to change implementation of service B from B_impl to B_imple2 ?.
With classical dependency injection it very hard to achieve this
because implemetation of A can cache reference to B and it will be
imposible to re-inject it!. The more flexible way to access services
is to use some sort of Service Locator it is also could becombined
with Dipendency Injection.
Daniel Pitts - 15 Feb 2007 18:20 GMT
> > > Yes.. but I have to be able reinitialize my singleton therefore
> this
[quoted text clipped - 37 lines]
> is to use some sort of Service Locator it is also could becombined
> with Dipendency Injection.
One solution:
Inject a single AtomicReference<B> instance into everything that needs
the service provided by B.
When the implementation of B used needs to change, update the atomic
reference.
Or, to "hide" this atomic reference:
class BDelegate implements B {
private final AtomicReference<B> ref = new AtomicReference<B>();
public BDelegate(B impl) {
ref.set(impl);
}
public void changeImpl(B newImpl) {
ref.set(newImpl);
}
// delegate B implementation to ref.get();
}
This also gives you the change to make "changeImpl" thread-safe. If
someone is in the middle of a multi-step action with the existing
previous B object, you can add proper synchronization to ensure that
the new impl isn't changed before it should be.