繁体   English   中英

关联消息和目标类实例创建的最佳实践

[英]Best practice to associate message and target class instance creation

我正在研究的程序具有分布式体系结构,更确切地说是Broker-Agent模式。 代理将向其相应的代理发送消息,以告知代理执行任务。 发送的每条消息均包含目标任务信息(任务名称,任务执行所需的配置属性等)。 在我的代码中,代理端的每个任务都在单独的类中实现。 喜欢 :

public class Task1 {}
public class Task2 {}
public class Task3 {}
...

消息采用JSON格式,例如:

{
  "taskName": "Task1",  // put the class name here
  "config": {

  }
}

因此,我需要将代理发送的消息与代理端的正确任务相关联。

我知道一种方法是将目标任务类名称放入消息中,以便代理能够通过使用反射从消息中提取的任务名称来创建该任务类的实例,例如:

Class.forName(className).getConstructor(String.class).newInstance(arg);

我想知道实现此关联的最佳实践是什么。 任务的数量在增加,我认为编写字符串很容易出错,而且不容易维护。

如果您对类名如此具体,甚至可以考虑序列化任务对象并直接发送它们。 这可能比反射方法更简单(尽管耦合甚至更紧密)。

但是通常您不希望Broker和Agent之间发生这种耦合。 经纪人需要知道存在哪些任务类型,以及如何以每个人都能理解的方式描述任务(例如JSON)。 它不/不应该知道代理如何执行任务。 甚至代理使用哪种语言编写。 (这并不意味着在两个代码库都通用的地方定义任务名称不是一个好主意)

因此,您只需要找到一种基于某种字符串在代理内部构造对象(或调用方法)的好方法。 常见的解决方案是某种形式的工厂模式,例如: http : //alvinalexander.com/java/java-factory-pattern-example-也很有帮助: Map<String, Factory>

interface Task {
    void doSomething();
}

interface Factory {
    Task makeTask(String taskDescription);
}

Map<String, Factory> taskMap = new HashMap<>();

void init() {
    taskMap.put("sayHello", new Factory() {
        @Override
        public Task makeTask(String taskDescription) {
            return new Task() {
                @Override
                public void doSomething() {
                    System.out.println("Hello" + taskDescription);
                }
            };
        }
    });
}

void onTask(String taskName, String taskDescription) {
    Factory factory = taskMap.get(taskName);
    if (factory == null) {
        System.out.println("Unknown task: " + taskName);
    }
    Task task = factory.makeTask(taskDescription);

    // execute task somewhere
    new Thread(task::doSomething).start();
}

http://ideone.com/We5FZk

如果您愿意,可以考虑使用基于注释的反射魔术。 取决于有多少个任务类。 投入更多的精力来解决隐藏复杂性的自动解决方案时,需要付出更多的努力。

例如,上面的Map可以通过添加一些类路径扫描来自动填充, 该类路径扫描使用包含字符串的批注来对正确类型的类进行添加。 或者,您可以让某个DI框架注入需要进入地图的所有内容。 大型项目中的DI通常可以很好地解决这类问题: https : //softwareengineering.stackexchange.com/questions/188030/how-to-use-dependency-injection-in-conjunction-with-the-factory-pattern

除了编写自己的发行系统之外,您还可以使用现有的发行系统。 (重用而不是重新发明是一种最佳实践)。 也许http://www.typesafe.com/activator/template/akka-distributed-workers或更一般的http://twitter.github.io/finagle/可以在您的环境下工作。 但是有太多其他涵盖不同方面的开源分布式事物来命名所有有趣的事物。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM