Singleton Design pattern with a twist - n00b

E

eladkatz

Hi all, i have a question about using the singleton DP in java.
say i want to make a debugger singleton, but i want to be able to pass
paramaters to it when it is first created.
that is - i want to pass a paramater i read called isDebugEnabled -
that decides in the loggers print method if i should print or not - how
can i pass it? should i pass it in the getInstance method or should i
use some kind of static member that has a default value and that is
changed directly?
i know that design-wise this isn't optimal and that it would be best if
the logger read the paramater itself and it wasn't passed to it,
however, this is not an option due to other design constaints...
i'd appreciate any help in this subject
thanks,
Elad.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Hi all, i have a question about using the singleton DP in java.
say i want to make a debugger singleton, but i want to be able to pass
paramaters to it when it is first created.
that is - i want to pass a paramater i read called isDebugEnabled -
that decides in the loggers print method if i should print or not - how
can i pass it? should i pass it in the getInstance method or should i
use some kind of static member that has a default value and that is
changed directly?
i know that design-wise this isn't optimal and that it would be best if
the logger read the paramater itself and it wasn't passed to it,
however, this is not an option due to other design constaints...
i'd appreciate any help in this subject
thanks,

I would probably use something like:

private static ConfigInfo confinfo;
public static setup(ConfigInfo cfg) {
if(instance == null) {
confinfo = cfg;
} else {
throw VeryBadException("Too late !");
}
}

Arne
 
D

Daniel Pitts

Arne said:
I would probably use something like:

private static ConfigInfo confinfo;
public static setup(ConfigInfo cfg) {
if(instance == null) {
confinfo = cfg;
} else {
throw VeryBadException("Too late !");
}
}

Arne

You need to syncronize the setup method.

Also, it should probably throw java.lang.IllegalStateException
public class MySingleton {
private static final Object sync;
private static MySingleton instance;
public static void setup(ConfigInfo config) {
synchronize(sync) {
if (instance != null) {
throw new IllegalStateException(
"MySingleton already initialized!"
);
}
instance = new MySingleton(config);
}
}

private final ConfigInfo config;
private MySingleton(ConfigInfo config) {
this.config = config;
}
}
 
E

eladkatz

Arne said:
I would probably use something like:

private static ConfigInfo confinfo;
public static setup(ConfigInfo cfg) {
if(instance == null) {
confinfo = cfg;
} else {
throw VeryBadException("Too late !");
}
}

Arne

thanks but the thing is - this means that whenever i get the singleton
(many places) i have to try/catch it and this will make my code very
hard to read and also much more complicated, there has to be a better
way...
 
P

Patricia Shanahan

thanks but the thing is - this means that whenever i get the singleton
(many places) i have to try/catch it and this will make my code very
hard to read and also much more complicated, there has to be a better
way...

Have you looked at java.util.logging? If not, I suggest doing so, to see
whether it meets your needs more simply than rolling your own.

Patricia
 
E

eladkatz

Patricia said:
Have you looked at java.util.logging? If not, I suggest doing so, to see
whether it meets your needs more simply than rolling your own.

Patricia
thanks for the answer, but the debugger example was just to illustrate
what i was talking about, in fact this is much more complex than that...
 
C

Chris Uppal

thanks but the thing is - this means that whenever i get the singleton
(many places) i have to try/catch it and this will make my code very
hard to read and also much more complicated, there has to be a better
way...

If there is the slightest chance that getting the singleton can fail, or that
using it can (in that way), then you have the wrong architecture.

Some suggestions:

Create the singleton as part of an explicit setup phase. That means that
you'd have "real" code somewhere which causes the singleton to be created and
which (and /only/ which) knows that it might fail, and knows what to do it when
it does.

If the attempt to create and configure a suitable singleton at that time, then
one simple option is the terminate the application. Another option would be to
log an error and continue with dummy object which was compatible with the
"real" singleton but which didn't do anything. A third option would be to
continue using some sort of reduced functionality/default configuration
fallback object in place of the "real" singleton.


BTW, from your earlier post:
say [...] i want to pass a paramater i read called isDebugEnabled -
that decides in the loggers print method if i should print or not - how
can i pass it? should i pass it in the getInstance method or should i
use some kind of static member that has a default value and that is
changed directly?

You clearly cannot pass the configuration information with every call to
getInstance() (or whatever less ill-chosen method name you actually choose),
since that would /totally/ destroy any point in using a singleton (or
singleton-like) pattern at all. So you have to initialise it statically. You
can do that implicitly as part of class initialisation, but there are two
problems with that:

1) It's awkward at best to arrange for proper error handing unless (as above)
you have an explicitly coded initialisation phase in your application startup.
2) You may find it difficult to manage the order of initialisation -- there
will probably be dependencies between different modules such that one is
expected to be initialised before another one initialises itself. If they are
at all complicated then it will probably be easer to manage such dependencies
explicitly rather than leaving it up to the classloading mechanism.

-- chris
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Oops.

There are missing a void in that line.
thanks but the thing is - this means that whenever i get the singleton
(many places) i have to try/catch

No.

This setup method is only intended to be called once at program
startup or similar.

Then you call your getInstance method many places unchanged.

The getInstance method implementation just uses confinfo.

Arne
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Daniel said:
You need to syncronize the setup method.
No.

Also, it should probably throw java.lang.IllegalStateException

Whatever.

Arne
 
E

eladkatz

Arne said:
Oops.

There are missing a void in that line.


No.

This setup method is only intended to be called once at program
startup or similar.

Then you call your getInstance method many places unchanged.

The getInstance method implementation just uses confinfo.

Arne

but what if setup was not called before getInstance - shouldnt it throw
an exception saying that the instance does not have a configInfo setup
(i.e. if confInfo == null)
 
D

Daniel Pitts

but what if setup was not called before getInstance - shouldnt it throw
an exception saying that the instance does not have a configInfo setup
(i.e. if confInfo == null)

Try it this way...

public class MySingleton {
private static final Object sync;
private static MySingleton instance;
public static void setup(ConfigInfo config) {
synchronize(sync) {
if (instance != null) {
throw new IllegalStateException(
"MySingleton already initialized!"
);
}
instance = new MySingleton(config);
}
}
public static MySingleton getInstance() {
if (instance == null) {
throw new IllegalStateException(
"MySingleton was not initialized!"
);
}
return instance;
}

private final ConfigInfo config;
private MySingleton(ConfigInfo config) {
this.config = config;
}
}


Since IllegalStateException is a RuntimeException, you don't need to
(and probably shouldn't) catch it. RuntimeExceptions, and Errors are
most often the result of a bug or a severe malfunction. When you get
them, you should usually just log the exception, and then perform a
clean-as-possible shutdown. Then you can use the log to figure out
what is causing it and fix the Bug.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

but what if setup was not called before getInstance - shouldnt it throw
an exception saying that the instance does not have a configInfo setup
(i.e. if confInfo == null)

If you can not place the setup call in some code you know for
sure are called before getInstance and you do not want to use
some default values, then getInstance could test for it.

Arne
 
J

John Ersatznom

thanks but the thing is - this means that whenever i get the singleton
(many places) i have to try/catch it and this will make my code very
hard to read and also much more complicated, there has to be a better
way...

Make it a runtime exception or better yet an error. And the setup is
only supposed to be called once, in main, unless you want that error's
stack trace and the message "Too late !" becoming eerily familiar to
you. It was the getInstance you want to use later. Of course you're in
for a fun session with NullPointerException if you forget to call setup
first.

More generally, why not use the static initializer and class loading
specification trick:

private static ConfigInfo info;
private static class Holder {
public static final MySingleton instance =
new MySingleton(info);
}
public static void setup (ConfigInfo inf) { info = inf; }
public static MySingleton getInstance () { return Holder.instance; }
public MySingleton (ConfigInfo info) { myInfo = info; }
private ConfigInfo myInfo;
....


The neat trick here is, Holder isn't loaded by the classloader until
there's an actual attempt to instantiate the class or invoke a static
method on it or access a static field or similarly. And then it's loaded
and its static initializer runs *atomically* -- i.e. thread-safely.

When that happens, the instance is constructed using the current value
of info, which of course is the last thing setup was called with before
the first call to getInstance executed. And null, of course, if setup
wasn't called soon enough.

The real beauty of it is that every later call to getInstance has the
blazingly fast performance of a single non-polymorphic, inlinable
function call and a single field access(!)...


Of course, for real generality, you create a DebugPolicy class -- not a
singleton -- and pass instances around as parameters, where they clutter
up method argument lists but allow you to use different ones in
different places, use a simple "debugPolicy = new OurPolicy(); ...
doSomething(debugPolicy) ..." in your main method, and so on. Of course,
a debugPolicy handled by multiple threads probably needs to synchronize
some stuff, aside from reads of read-only data. If it doesn't need to
have shared state across threads, giving separate instances to separate
threads makes sense. If you don't care about taking a huge performance
hit you can even make them thread locals and avoid the extra arg in all
your method signatures.

Or you can use a cute little buzzword-compliant singleton. Just please
pass on that bad batch of double checked locking that's been going
around. Anyone running a pre-1.5 JRE will have potential problems even
if you use "volatile".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top