私は、専門業務と訪問者パターンを持つ複数の葉ノードクラスを持つ複合パターンを使用しています。この例では、分かりやすくするためにすべての明白なaccept
メソッドを除外しました。訪問者パターンとコンポジットパターンを使用してフィルタリングされたストリームを構築する
interface Command {
public int getCost();
}
class SimpleCommand implements Command {
private int cost;
public int getCost() {
return cost;
}
}
class MultiCommand implements Command {
private Command subcommand;
private int repeated;
public int getCost() {
return repeated * subcommand.getCost();
}
public void decrement() {
if (repeated > 0)
repeated--;
}
}
class CommandList implements Command {
private List<Command> commands;
public int getCost() {
return commands.stream().mapToInt(Command::getCost).sum();
}
public void add(Command command) {
commands.add(command);
}
}
interface CommandVisitor {
default void visitSimpleCommand(SimpleCommandCommand command) { }
default void visitMultiCommand(MultiCommand multiCommand) { }
default void visitCommandList(CommandList commandList) { }
}
訪問者を作成してdecrement
などの操作を実行できるようになりました。
class MultiCommandCollector implements CommandVisitor {
private final Stream.Builder<MultiCommand> streamBuilder = Stream.builder();
public static Stream<MultiCommand> streamFor(Command command) {
MultiCommandVisitor visitor = new MultiCommandVisitor();
command.accept(visitor);
return visitor.streamBuilder.build();
}
public void visitMultiCommand(MultiCommand multiCommand) {
builder.accept(multiCommand);
}
}
これは、あなたが期待するとして使用されます。しかし、私はそれが簡単に任意の操作がそれらに対して実行できるように、特定のクラスのオブジェクトをストリーム汎用訪問者を作成するために見つけます。たとえば、
MultiCommandCollector.streamFor(command).forEach(MultiCommand::decrement);
これには1つの重要な制限があります。これは、ストリームが処理されるときに階層を変更するために使用できません。たとえば、次のように失敗した:
CommandListCollector.streamFor(commandList).forEach(cl -> cl.add(command));
私はこれを可能にする代替エレガントなデザインを考えることはできません。
私の質問は、階層を変更できる汎用ビジターを許可するためにこのデザインが自然に拡張されていますか?言い換えれば、ビジターが1人のメンバーにアクセスして階層を更新してから次のメンバーにアクセスできる方法はありますか?これはストリームの使用に対応していますか?