2012-02-08 2 views
5

Я изо всех сил, чтобы сделать эту работу:Java дженериков абстрактная фабрика выпуск

public abstract class MapperFactory<M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> { 

    public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

    public abstract TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper(); 

    public static class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> { 

     @Override 
     public TaskMapper<? extends Message, ? extends Message, ? extends TaskForm> getTaskMapper() { 
      return new MyTaskMapper(); 
     } 

    } 
} 

public interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> { 

    public F fillForm(I msgIn, O msgOut, F taskForm); 

    public O fillMsgOut(F taskForm); 
} 

public class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm > { 

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut, 
      MyTaskForm taskForm) { 
     return null; 
    } 

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) { 
     return null; 
    } 

} 

Проблема есть ошибка компиляции:

Type mismatch: cannot convert from MapperFactory.MyTaskMapperFactory to MapperFactory

в моем MapperFactory здесь:

if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

Любые идеи, как исправить эту ошибку?

Конечно замена:

public static <M extends TaskMapper<? extends Message, ? extends Message, ? extends TaskForm>> MapperFactory<M> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

с:

public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) { 

     if (msgIn.isMyMapper()) 
      return new MyTaskMapperFactory(); 

     throw new IllegalStateException("Mapper not found!"); 
    } 

будет работать, но это не тот ответ, который я ищу.

Это, как представляется, проблема с общим абстрактным шаблоном завода в целом. Ответы на предоставление исходных образцов с использованием настраиваемых объектов также приветствуются.

+0

'MAPPER' не является хорошим именем класса, следующего за Java-соглашениями. –

+0

Пожалуйста, сделайте имена своих классов как можно более маленькими (но все же четкими). И переименовать 'MAPPER' в' Mapper'? Названия странных/длинных классов просто путают/загромождают вопрос * и * ответы. – Bohemian

+0

@his MAPPER - это не имя класса. Это имя типа Generic типа T в HashMap

ответ

4

Согласно Effective Java, 2-е издание, пункт 28:

If a type parameter appears only once in a method declaration, replace it with a wildcard.

Ваш метод getMapperFactory использует только параметр M типа в тип возвращаемого значения. После этого совет дает метод следующую подпись, и метод компилирует:

public static MapperFactory<? extends TaskMapper<Message, ? extends Message, ? extends String>> getMapperFactory(Message msgIn, Message msgOut) 

EDIT: Чем больше я смотрю на код, тем больше я думаю MapperFactory не должен быть параметризованы. Этот параметр здесь не используется, getTaskMapper возвращает TaskMapper.

+2

Даже короче, подпись может быть просто публичной статической MapperFactory getMapperFactory() '. Этот метод не ограничивает ни один из параметров типа больше, чем подпись класса для «MapperFactory». То же самое относится к 'public abstract TaskMapper getTaskMapper()'. (Это также может быть «публичный абстрактный M getTaskMapper()», не может определить, что такое замысел за параметром типа.) * «Если у вас есть сомнения, используйте меньше генериков» *, вероятно, является хорошим правилом. – millimoose

1

Ответное заявление отлично работает с приведением типов:

return (BpmMapperFactory<MAPPER>)new Bpm007PrepareDocTaskMapperFactory(); 

Этого код никогда не будет выполняться, хотя в его нынешнем виде, поскольку Bpm007PrepareDocTaskMapper не распространяется BpmCommonMessageDto, так msgIn не может быть экземпляром Bpm007PrepareDocTaskMapper.

+0

Я отредактировал часть 'if' -thanks для информации, которая еще не была закончена, и здесь это не актуально. Любой способ избежать бросков? –

1

Мое решение будет убивать столько дженериков, как это возможно с огнем:

abstract class MapperFactory<M extends TaskMapper<?, ?, ?>> { 

    public static MapperFactory<?> getMapperFactory(Message msgIn, Message msgOut) { 
     if (msgIn.isMyMapper()) return new MyTaskMapperFactory(); 
     throw new IllegalStateException("Mapper not found!"); 
    } 

    public abstract M getTaskMapper(); 
} 


class MyTaskMapperFactory extends MapperFactory<MyTaskMapper> { 

    @Override 
    public MyTaskMapper getTaskMapper() { 
     return new MyTaskMapper(); 
    } 

} 


interface TaskMapper<I extends Message, O extends Message, F extends TaskForm> { 

    public F fillForm(I msgIn, O msgOut, F taskForm); 

    public O fillMsgOut(F taskForm); 

} 

class MyTaskMapper implements TaskMapper<IncomingMessage, OutgoingMessage, MyTaskForm> { 

    public MyTaskForm fillForm(IncomingMessage msgIn, OutgoingMessage msgOut, MyTaskForm taskForm) { 
     return null; 
    } 

    public OutgoingMessage fillMsgOut(MyTaskForm taskForm) { 
     return null; 
    } 

} 

Это действительно нет необходимости повторять параметры типа одного класса в каждом методе, который использует его, если вы этого не сделаете действительно заботятся о том, что они есть или не нуждаются в том, чтобы сдерживать их больше, чем подпись класса.

Смежные вопросы