Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用访问者和复合模式构建过滤流_Java_Design Patterns_Composite_Visitor Pattern - Fatal编程技术网

Java 使用访问者和复合模式构建过滤流

Java 使用访问者和复合模式构建过滤流,java,design-patterns,composite,visitor-pattern,Java,Design Patterns,Composite,Visitor Pattern,我正在使用一个复合模式,其中包含多个叶节点类,这些叶节点类具有专家操作和访问者模式,以允许执行这些操作。在本例中,为了清晰起见,我省略了所有明显的accept方法 interface Command { public int getCost(); } class SimpleCommand implements Command { private int cost; public int getCost() { return cost; } }

我正在使用一个复合模式,其中包含多个叶节点类,这些叶节点类具有专家操作和访问者模式,以允许执行这些操作。在本例中,为了清晰起见,我省略了所有明显的
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) { }
}
正如您所期望的那样使用它。例如:

MultiCommandCollector.streamFor(command).forEach(MultiCommand::decrement);
这有一个显著的限制:它不能在处理流时用于更改层次结构。例如,以下操作失败:

CommandListCollector.streamFor(commandList).forEach(cl -> cl.add(command));
我想不出另一种优雅的设计可以做到这一点


我的问题是:这个设计是否有一个自然的扩展,允许一个通用访问者也可以改变层次结构?换句话说,是否有一种方式可以让访问者访问一个成员,然后在访问下一个成员之前刷新层次结构?这与流的使用兼容吗?

根据我以前的经验,访问者模式对于查询或重新创建层次结构都很有用。查询部分很明显——您只需侦听特定类型的子对象,然后根据需要构建查询结果。另一个问题,改变等级制度,则更加困难

在遍历层次结构时,可能很难更改层次结构。因此,我知道两种有用的技术在实践中效果很好

  • 访问层次结构时,生成要更改的对象列表。 在访问完成之前不要更改它们。具体访客 可以将感兴趣的对象列表构建为其私有成员。一旦 完成访问后,它将显示对象列表作为其结果。 然后才开始遍历结果列表并对其进行更改 物体
  • 访问层次结构时,在访问元素时,创建 元素。如果需要更改元素,则构建更改的 版本否则,如果元素不需要更改,只需将其作为 新元素。完成整个访问后,您将拥有新的层次结构 按照预期进行所有修改。旧的等级制度可能是 然后取消引用,垃圾收集器将收集 已经换成了新的
  • 第一种算法适用于元素可变的情况。第二种算法适用于元素不可变的情况

    希望这有帮助

    CommandListCollector.streamFor(commandList).forEach(cl -> cl.add(command));