Factory design pattern question

Discussion in 'Java' started by Chris, Jan 5, 2007.

  1. Chris

    Chris Guest

    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.)
     
    Chris, Jan 5, 2007
    #1
    1. Advertising

  2. Chris

    Daniel Pitts Guest

    Chris wrote:
    > 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.
     
    Daniel Pitts, Jan 5, 2007
    #2
    1. Advertising

  3. Chris

    Guest

    > 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!
     
    , Jan 5, 2007
    #3
  4. Chris

    Mark Rafn Guest

    Chris <> wrote:
    >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.
    --
    Mark Rafn <http://www.dagon.net/>
     
    Mark Rafn, Jan 5, 2007
    #4
  5. Mark Rafn wrote:
    > 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).
     
    John Ersatznom, Jan 8, 2007
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Medi Montaseri
    Replies:
    17
    Views:
    914
    Medi Montaseri
    Sep 3, 2003
  2. sunny
    Replies:
    1
    Views:
    478
    Salt_Peter
    Dec 7, 2006
  3. C#
    Replies:
    4
    Views:
    434
  4. Pallav singh
    Replies:
    0
    Views:
    410
    Pallav singh
    Jan 22, 2012
  5. Pallav singh
    Replies:
    0
    Views:
    433
    Pallav singh
    Jan 22, 2012
Loading...

Share This Page