【问题标题】:How to use HashMap as builder?如何使用 HashMap 作为构建器?
【发布时间】:2016-10-28 20:09:05
【问题描述】:

我正在尝试根据到达我的字符串参数运行一些方法。 这个想法是从“终端”列表中激活和停用某些功能。 该类是为命令模式设计的,“doProcess”将在一段时间内被调用

我的实际解决方案很糟糕,所以我考虑制作一个 HashMap。例如: map.put("邮件",activateMailsOfTerminals)

但我不知道如何根据构造函数上的字符串列表动态调用函数(activateMailsOfTerminals、deactivate...)

非常感谢!

糟糕的解决方案:

public class ActionsActivator {

    Set < Terminal > terminals = new HashSet < > ();
    Set < String > activate = new HashSet < > ();
    Set < String > deactivate = new HashSet < > ();

    public ActionsActivator(Set < Terminal > filteredTerminals, Set < String > active, Set < String > deactive) {
        this.terminals = Map().getInstance().getTerminals;
        this.activate.addAll(activate);
        this.deactivate.addAll(deactivate);
    }

    public void doProcess() {
        if (hasElement(activate, "Mail")) terminals.forEach(terminal - > terminal.activateMails());
        if (hasElement(activate, "Register")) terminals.forEach(terminal - > terminal.activateRegisters());

        if (hasElement(deactivate, "Mail")) terminals.forEach(terminal - > terminal.deactivateMails());
        if (hasElement(deactivate, "Register")) terminals.forEach(terminal - > terminal.deactivateRegisters());
    }

    private Boolean hasElement(Set < String > list, String element) {
        return list.stream().anyMatch(elem - > elem.equals(element));
    }
}

【问题讨论】:

  • 因此,您当前的解决方案对方法 activateMails()activateRegiters() 的调用进行了硬编码。我是否正确理解您希望能够将这些函数传递给构造函数?
  • 不一定,我只是不想检查字符串(hasElement 和 ifs)。最好的方法是只使用字符串参数列表调用方法

标签: java hashmap command-pattern


【解决方案1】:

如果我的理解是正确的,那么您有一组“终端”,并且您想要一个在“激活”时在提供的终端上执行某些方法调用/调用的对象。以下应完成并演示:

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class CommandsDemo {

    public static class ActionsActivator{
        private Set<Terminal> terminals;
        private Set<Consumer<Terminal>> actionsToPerformOnTerminals = new HashSet<>();

        public ActionsActivator(Set<Terminal> terminals, Consumer<Terminal>... actionsForTerminals){
            this.terminals = terminals;
            actionsToPerformOnTerminals.addAll(Arrays.asList(actionsForTerminals));
        }

        public void doProcess(){
            for(Consumer<Terminal> action : actionsToPerformOnTerminals){
                terminals.stream().forEach(action);
            }
        }
    }

    public static class Terminal{
        private final String name;

        public Terminal(String name){
            this.name = name;
        }

        public void activateMails(){
            System.out.println("Activated mail for: "+name);
        }
        public void activateRegisters(){
            System.out.println("Activated registers for: "+name);
        }
    }

    public static void main(String[] args){
        Terminal terminalA = new Terminal("terminalA");
        Terminal terminalB = new Terminal("terminalB");
        Terminal terminalC = new Terminal("terminalC");

        Set<Terminal> terminals = new HashSet<>();
        terminals.addAll(Arrays.asList(terminalA, terminalB, terminalC));

        ActionsActivator mailActivator = new ActionsActivator(terminals, (terminal)->terminal.activateMails());

        ActionsActivator registerActivator = new ActionsActivator(terminals, (terminal)->terminal.activateRegisters());

        ActionsActivator mailAndRegisterActivator = new ActionsActivator(terminals, 
                (terminal)->terminal.activateMails(),
                (terminal)->terminal.activateRegisters());

        System.out.println("Running mail activator");
        mailActivator.doProcess();

        System.out.println("Running register activator");
        registerActivator.doProcess();

        System.out.println("Running mail & register activator");
        mailAndRegisterActivator.doProcess();
    }

}

输出:

Running mail activator
Activated mail for: terminalC
Activated mail for: terminalA
Activated mail for: terminalB
Running register activator
Activated registers for: terminalC
Activated registers for: terminalA
Activated registers for: terminalB
Running mail & register activator
Activated registers for: terminalC
Activated registers for: terminalA
Activated registers for: terminalB
Activated mail for: terminalC
Activated mail for: terminalA
Activated mail for: terminalB

使我们能够配置在每个终端上调用的命令/命令的关键是通用Consumer 类,它代表了使用通用声明类型的对象实例调用的能力作为论据。例如:

Consumer<String> myConsumer = (str)->{System.out.println("Hello, "+str)};

myConsumer.accept("World");
myConsumer.accept("Venus");
myConsumer.accept("Mars");

打印:

Hello, World
Hello, Venus
Hello, Mars

因此,通过传入一系列消耗TerminalConsumer&lt;Terminal&gt; 对象并在所述Terminals 上调用所需的方法,我们可以创建一个ActionsActivator,它在提供的终端上调用可配置的方法/方法.

【讨论】:

  • 太棒了!非常感谢您的宝贵时间
  • 谢谢。请参阅编辑以解释 Consumer 在完成这项工作中所起的关键作用。
【解决方案2】:

使用地图:

private static Map<String, Consumer<Terminal>> activations = new HashMap<String, Consumer<Terminal>>() {{
    put("Mail", Terminal::activateMails);
    put("Register", Terminal::activateRegisters);
    // etc
}};
// similar for deactivate

然后使用:

public void doProcess() {
    activate.stream()
        .map(activations::get)
        .filter(a -> a != null)
        .forEach(a -> terminals.forEach(a));
    // similar for deactivate
}

这种方法以声明方式处理任意数量的操作。

【讨论】:

    猜你喜欢
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 2014-05-28
    • 1970-01-01
    • 2011-06-06
    相关资源
    最近更新 更多