Factory design pattern question

C

Chris

I would like to use some of the new functionality in JDK 1.5 and 6, but
I have to run under 1.4. I've managed to duplicate the needed
functionality in 1.4 using an inefficient method.

If my app is running in 1.5, I'd like it to use the native function,
else use my slow/ugly function.

What's the best way to set up a Factory to return the appropriate class?
The class I need does *not* implement an interface that exists in 1.4.

The best method that I've been able to come up with uses an excessive
number of interfaces and abstract classes. There's probably a better way.

(The function I need is read-write locking in the concurrency utilities,
though I don't that matters for this question.)
 
D

Daniel Pitts

Chris said:
I would like to use some of the new functionality in JDK 1.5 and 6, but
I have to run under 1.4. I've managed to duplicate the needed
functionality in 1.4 using an inefficient method.

If my app is running in 1.5, I'd like it to use the native function,
else use my slow/ugly function.

What's the best way to set up a Factory to return the appropriate class?
The class I need does *not* implement an interface that exists in 1.4.

The best method that I've been able to come up with uses an excessive
number of interfaces and abstract classes. There's probably a better way.

(The function I need is read-write locking in the concurrency utilities,
though I don't that matters for this question.)

Why a number of interfaces? Why not one interface and two concrete
classes? The first concrete class delegates to the native approach,
the other concrete class delegates to your 1.4 implementation.

Although, I wonder if this will work at all. I seem to recall reading
that 1.5 class files aren't compatible with the 1.4 JVM.
Even if that wasn't the case, you'll have to do some ugly compiler
tricks to make it work correctly.
 
G

grasp06110

The class I need does *not* implement an interface that exists in 1.4.

Is the interface implemented in 1.5? If yes what is it?

Also, compiled 1.5 byte code is *supposed* to run on a 1.4 VM so you
might be able to get away with writing a single class, compiling it
under 1.5 and running it on both 1.4 and 1.5 jre. I'd write a couple
of unit tests and give it a try. You could probably even fork and set
the JAVA_HOME variable on the fly if you use something like ANT to run
your tests.

Good Luck!
 
M

Mark Rafn

Chris said:
I would like to use some of the new functionality in JDK 1.5 and 6, but
I have to run under 1.4. I've managed to duplicate the needed
functionality in 1.4 using an inefficient method.

There's not much in 1.5 that can't be just as efficient in 1.4. It may be
more work than you want to do to backport though.
If my app is running in 1.5, I'd like it to use the native function,
else use my slow/ugly function.

Ok. So you need to compile it for 1.4. Depending on exactly how your code
works, you might be able to just use the -target 1.4 flag to the 1.5 javac,
but it's more likely that you'll want to actually compile it with a real 1.4
JDK. That way you get the right libraries and everything that the 1.4 JRE
will expect.
What's the best way to set up a Factory to return the appropriate class?
The class I need does *not* implement an interface that exists in 1.4.

Write a factory for whatever 1.4-extant interface you want to expose. This
could be built in to the JDK, or one you define in your code. You'll write
two implementations - one that works under 1.4 and one under 1.5. If you need
to compile the 1.5 one with a 1.5 JDK, you can do so, and drop it into the
same JAR as the 1.4 code for the rest of the app.

Your factory can test the system property java.class.version - if it's 49 or
higher, then JDK1.5 classes can be loaded using Class.forName(). If it's 48
or less, then only JDK1.4 classes are avaialable, and you can use your
version.

There are other ways to do this as well, which may be better for different
needs.
The best method that I've been able to come up with uses an excessive
number of interfaces and abstract classes. There's probably a better way.
(The function I need is read-write locking in the concurrency utilities,
though I don't that matters for this question.)

In that case, just grab Doug Lea's "util.concurrent" package and use it for
both. This is pretty much the same code that became java.util.concurrent
in JDK1.5.
 
J

John Ersatznom

Mark said:
Your factory can test the system property java.class.version - if it's 49 or
higher, then JDK1.5 classes can be loaded using Class.forName(). If it's 48
or less, then only JDK1.4 classes are avaialable, and you can use your
version.

Reflection ... ugh. And is it even necessary? What if you have

public abstract class A {
// Compiled with 1.4
public abstract void foo ();
}

public class B extends A {
// Compiled with 1.4
public void foo () {
// Do stuff without using 1.5-only library classes
}
}

public class C extends A {
// Compiled with 1.5
public void foo () {
// Do stuff using 1.5-only library classes
}
}

public class AFactory {
public static A getA () {
if (jre is 1.5) return new C();
return new B();
}
}

public class Main {
public static void main (String[] args) {
A myA = AFactory.getA();
myA.foo();
}
}

Assume the test in getA works perfectly. In a 1.4 JRE, getA returns a B
and C's never constructed or even invoked somehow statically, so class C
never even gets loaded. The classloader certainly doesn't try to load
the 1.5-specific dependencies C's foo method references (then fail, then
complain). It probably doesn't even see the C.class file's contents at
all (and maybe complain about something 1.5-specific in that).

In a 1.5 JRE, getA returns a C, so the classloader loads C.class in
getA. C.class may (but probably doesn't) cause problems if a 1.4 VM
loads it, but a 1.5 VM loads it. Calling C's constructor may invoke
1.5-specific library code, but the 1.5 library is present. Calling foo
from main definitely calls 1.5 library code, but again the 1.5 library
is present for the classloader to find.

Unless there's something subtle I'm missing here, there's no apparent
need for reflectively loading classes (such as C) explicitly here (in
getA or elsewhere).
 

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
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top