简体   繁体   中英

Factory method to instantiate instance of objects used in a generic class

I have the following classes.

public abstract class AbstractClass {

      protected String value1;

      public void setValue1(String value1) {
           this.value1 = value1;
      }

}

public abstract class ConcreteClass1 extends AbstractClass{

}

public abstract class ConcreteClass2 extends AbstractClass {

}

public class FactoryOfAbstractClass {

   public AbstractClass newInstance(Class responseType) {
      if (responseType == ConcreteClass1.class) {
         return new ConcreteClass1();
      } else if (responseType == ConcreteClass2.class) {
         return new ConcreteClass2();
      }
      return null;

}

public abstract class ServiceClass<T extends AbstractClass> {

   public T method1 (String arg1, String arg2, Class responseType) {

      //Some operations resulting in a variable called value1
      String value1= someOp();
      T result = FactoryOfAbstractClass.newInstance(responseType);
      result.setValue1(value1);
      return result;

   }

}

In line T result = FactoryOfAbstractClass.newInstance(responseType); I get a compilation error saying I need to typecast the object I'm getting to T. I don't understand the compilation error since my factory method is returning an instance of Abstract class and the service class's generic T extends AbstractClass .

The compilation issue goes away once I cast it to T. But I don't understand why we need to typecast it in the first place. Why is the typecasting needed?

The other option is to not use a Factory and instead go with responseType.newInstance() . But that internally uses reflections and I want to avoid them. Is there any other approach i can take for this?

I don't understand the compilation error since my factory method is returning an instance of Abstract class and the service class's generic T extends AbstractClass

Let's replace AbstractClass with Car for a more understandable explanation. Suppose a programmer create a ServiceClass<Mercedes> (Mercedes is a typeof Car, right?). FactoryOfAbstractClass.newInstance() 's return type is Car . So the compiler has no idea of the concrete type of Car returned by this method. It could be a Mercedes, but it could also be a Ford, or a Peugeot, or a Volskwagen. But you assign the result to T (which, in this case, is Mercedes ). So that can't compile without a cast.

Frankly, this factory is completely unnecessary. Since the caller is supposed to pass the class to use anyway, you could just take an instance of that class instead of a factory, and thus let the caller create the instance. Or you could take a Supplier<AbstractClass> as argument, and the caller would just have to pass ConcreteClass1::new . That would make the code simpler, safer, and more extensible (since you wouldn't be limited to only two known subclasses).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM