Фабричный метод для создания экземпляров объектов, используемых в универсальном классе - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть следующие классы.

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;

   }

}

В строке T result = FactoryOfAbstractClass.newInstance(responseType); я получаю ошибку компиляции, говорящую, что мне нужно типизировать объект, который я получаю к T. Iне понимаю ошибка компиляции , так как мой метод фабрики возвращает экземпляр класса Abstract и универсальный класс обслуживания T extends AbstractClass.

Проблема компиляции исчезает, как только я приведу ее к TНо я не понимаю, почему мы должны в первую очередь настраивать его.Зачем нужна приведение типов?

Другой вариант - не использовать фабрику и вместо этого идти с responseType.newInstance().Но это внутренне использует отражения, и я хочу их избежать.Есть ли другой подход, который я могу использовать для этого?

1 Ответ

0 голосов
/ 15 сентября 2018

Я не понимаю ошибку компиляции, так как мой метод фабрики возвращает экземпляр класса Abstract, а универсальный T класса сервиса расширяет AbstractClass

Давайте заменим AbstractClass на Car для более понятного объяснения. Предположим, программист создал ServiceClass<Mercedes> (Mercedes - это тип автомобиля, верно?). FactoryOfAbstractClass.newInstance() тип возвращаемого значения Car. Таким образом, компилятор не имеет представления о конкретном типе Car, возвращаемом этим методом. Это может быть «Мерседес», но это может быть и «Форд», или «Пежо», или «Вольскваген». Но вы присваиваете результат T (который в данном случае равен Mercedes). Так что это не может скомпилироваться без приведения.

Честно говоря, эта фабрика совершенно не нужна. Так как вызывающий должен передать класс для использования в любом случае, вы можете просто взять экземпляр этого класса вместо фабрики и, таким образом, позволить вызывающему создать экземпляр. Или вы могли бы взять Supplier<AbstractClass> в качестве аргумента, и вызывающий абонент просто должен передать ConcreteClass1::new. Это сделает код более простым, безопасным и расширяемым (поскольку вы не будете ограничены только двумя известными подклассами).

...