3
\$\begingroup\$

I have a hierarchy of types in my program and need to be able to create them dynamically at runtime. The solution I've come up with below is not the most elegant solution. Are there ways of improving it?

Specifically would it be possible to have the method getBuilderFor(...) not need to instantiate the type it's trying to create in order to get a builder for that type?

public class Main {
 public interface E { }
 public class EImpl implements E { }
 public interface C<V> extends E {
 interface Builder<T> { T build(); }
 }
 public abstract class CImpl<T> extends EImpl implements C<T> {
 public abstract class BuilderImpl<V extends C<?>> implements Builder<V>{ }
 }
 public interface B extends C<String> { }
 public class BImpl extends CImpl<String> implements B {
 public class BuilderImpl extends CImpl<B>.BuilderImpl<B> {
 @Override public B build() { return new BImpl(); }
 }
 }
 public interface D extends C<Double> { }
 public class DImpl extends CImpl<Double> implements D {
 public class BuilderImpl extends CImpl<D>.BuilderImpl<D> {
 @Override public D build() { return new DImpl(); }
 }
 }
 public class Factory {
 public <R extends C<?>, K extends C.Builder<R>> K getBuilderFor(final Class<R> type) {
 if (BImpl.class.equals(type)) {
 // I would ideally like to just have return BImpl.BuilderImpl() here - is it possible?
 return (K) new BImpl().new BuilderImpl();
 } else if (DImpl.class.equals(type)) {
 // I would ideally like to just have return DImpl.BuilderImpl() here - is it possible?
 return (K) new DImpl().new BuilderImpl();
 }
 return null;
 }
 }
}
palacsint
30.3k9 gold badges82 silver badges157 bronze badges
asked May 19, 2012 at 14:56
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Why not use a map of types (CImpl concrete instances) that are instantiated upon Factory initialization? The values of the map would be instances of BImpl, DImpl, etc, and the respective keys would be the types. The function getBuilderFor() would just do a map lookup and on the value returned from the map, call BuilderImpl() and return the result.

This approach would allow to avoid the if/else block. Additionally, it would make it easier and more elegant to add more types in the future.

palacsint
30.3k9 gold badges82 silver badges157 bronze badges
answered May 19, 2012 at 17:33
\$\endgroup\$
1
\$\begingroup\$
  1. The BuilderImpl classes can't be an inner (i.e. non-static) class of the class what it build. You have to create the builder first, then the builder will create the actual class. If the builder is an inner class it's not possible.

    (To make the BuilderImpl classes static you need to make static some other classes too.)

  2. The V type parameter on C looks unnecessary since the interface does not use it.

    public interface C<V> extends E {
     interface Builder<T> { 
     T build(); 
     }
    }
    
answered May 20, 2012 at 0:09
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.