2017-07-31 8 views
3

Java 8で動作するSpringブートアプリケーションでは、さまざまな種類のコマンドを処理するための一般的な動作を実装したいと考えています。Java 8ストリームとジェネリックインターフェイスの連鎖の責任パターン

以下のコードは、私が念頭に置いていたソリューションを示しています。

コマンド

public interface Processor<C extends Command> { 
    TypeCommand getCommandType(); 
    void processCommand(C command); 
} 

public abstract class AbstractProcessor<C extends Command> implements Processor<C> { 
    @Override 
    public void processCommand(C command) { 
     // Some common stuff 
     // ... 

     // Specific process 
     Result result = executeCommand(command); 

     // More common stuff 
     // ... 
    } 

    protected abstract Result executeCommand(C command); 
} 

@Component 
public AddCommandProcessor extends AbstractProcessor<AddCommand> { 

    @Override 
    protected Result executeCommand(AddCommand addCommand) { 
     // Execute command 
     // ... 
     return result; 
    } 

    @Override 
    public TypeCommand getCommandType() { 
     return TypeCommand.ADD_COMMAND; 
    } 
} 

汎用のプロセッサパターン:責任のチェーンと

public abstract class Command { 
    private final String uid; 
    private final LocalDateTime creationDate; 
    private final TypeCommand type; 
    // Constructor and getters omited ... 
} 

public class AddCommand extends Command { 
    private final Double amount; 
    // Constructor and getters omited ... 
} 

サービス:

@Service 
public class MyService { 

    private final List<Processor<? extends Command>> processors; 

    @Autowired 
    public MyService(final List<Processor<? extends Command>> processors) { 
     this.processors = processors; 
    } 

    public void processCommand(final Command command) { 
     processors.stream() 
      .filter(p -> command.getType() == p.getCommandType()) 
      .findFirst() 
      .ifPresent(processor -> processor.processCommand(command)); 
    } 
} 

残念ながら、このコードはコンパイルされません。ライン:

.ifPresent(processor -> processor.processCommand(command)); 

は、メッセージでコンパイルに失敗しました

processCommand(capture <? extends Command>) in Processor cannot be applied to (Command) 

私が意図したとおりにそれを行うには、他の方法が表示されません。どこが間違っていますか?

ありがとうございます。

+3

'プライベート最終リスト<プロセッサ<?あなたができるならhttps://stackoverflow.com/questions/5857561/java-generics-fancy-capture-collision –

+5

[PECS(プロデューサー)とは何ですか?コンシューマースーパーを拡張しますか?]](https://stackoverflow.com/q/2723397/2711488) – Holger

+0

'private final List > processors;を 'private final List > processors;'にコンパイルしますが、Springはプロセッサの実装をコレクションに挿入しません。 '( – CrakBoom

答えて

1

あなたは@SuppressWarnings("rawtypes")

.ifPresent(processor -> ((Processor) processor).processCommand(command)); 

別の方法でミュートすることができ、生タイプについての警告にエラーを変革なるだけProcessor processorProcessor<? extends Command> processorにジェネリックをドロップすることができるはずはprocessCommandはジェネリックとアップキャストすることです

public <C extends Command> void processCommand(final C command) { 
    processors.stream() 
     .filter(p -> command.getType() == p.getCommandType()) 
     .findFirst() 
     .map(processor -> (Processor<C>) processor) 
     .ifPresent(processor -> processor.processCommand(command)); 
} 

あなたがでミュートすることができます未チェックのキャストについて警告を与える。このような一般的なタイプ、へ。

特定TypeCommandを返しCommandは、(最初​​の)その型のサブクラスではない場合、これらの方法の両方がClassCastExceptionをスローしProcessorSubCommand戻りTypeCommand.ADD_COMMAND場合、同じTypeCommandを期待(例えば返していないがAddCommandのサブクラス)。

+0

両方のメソッドが動作します。ここでは「ClassCastException」は問題ではなく、 'TypeCommand'値によって' Command'実装が1つしかありません。 ! – CrakBoom

関連する問題