我的问题是如何将操作放入链中,以便在操作处理过程中传递额外的参数。
让我们考虑简单的过程链。输入是一个表示图像的对象。首先调整映像的大小,然后将其部署到ftp并保存到db中。使用责任链模式,调用可能如下所示:
ImageProcessor p = new ImageResizer(desiredSize);
p.setNext(new (new ImageDeployer(ftpServer, path)));
p.setNext(new (new ImageDbSaver(dbConnection, table)));
p.process(image);
p.close();这对于一幅图像来说是完美的。我想在一个循环中处理图像,并设置desiredSize和路径。我不能每次创建和关闭连接,因此必须传播代码:
ImageProcessor p = new ImageResizer();
p.setNext(new (new ImageDeployer(ftpServer)));
p.setNext(new (new ImageDbSaver(dbConnection, table)));
for(Image image : images) {
p.process(image, size, path);
}
p.close();解决方案的一个问题是,ImageProcessor不应该知道大小和路径。如果只使用ImageDbSaver参数,比如大小和路径就没有意义了。
有什么更好的方法来做呢?
发布于 2013-07-31 21:16:57
我想,在您的情况下,最健壮的解决方案是添加某种处理上下文。
在最简单的情况下,您可以(1)为此使用(例如Map<String, Object> ),(2)用特定于各种处理器的参数包装它,(3)将它传递到p.process(...)中,(4)然后提取(例如,在调整图像大小的处理器中的size )。
这样,您就可以灵活地添加新的参数,而无需更改ImageProcessor的签名,并保持实现者之间的解耦。
类似的实际例子是Java中的请求\session\servlet上下文。您可以在不同的生命周期阶段(例如,关于urls应该需要什么的安全配置选项)将内容放入其中,然后在需要的地方获取这些东西(例如,在过滤器中阻止\允许基于auth需求访问资源)。
更新
用代码示例更新答案以演示这个想法。
因此,在代码中的某个地方,您可以构建处理器链:
ImageProcessor p = new ImageResizer(desiredSize);
p.setNext(new (new ImageDeployer(ftpServer, path)));
p.setNext(new (new ImageDbSaver(dbConnection, table)));在(可能的)其他地方创建和配置处理上下文(并不需要在一个地方配置所有处理器):
Map<String, Object> context = new HashMap<String, Object>();
context.put("image_width", new Integer(640));在代码中的另一个地方,您可以进行处理,将上下文传递给它(我在所有处理过程中重用上下文,但您可能对每个图像使用不同的上下文):
for(Image image : images) {
p.process(image, context);
}
p.close();现在,在ImageResizer的某个地方
@Override
void process(Image image, Map<String, Object> context) {
// ...
Integer imageWidth = (Integer) context.get("image_width");
// ...
}因此,上下文是一个常见的地方,它帮助将数据传递到特定的处理器,抽象出有关这些数据的详细信息,从而使特定处理器相互分离。
发布于 2013-07-31 21:30:30
一个简单的解决方法是在循环之外构造不变量。例如:
ImageDeployer deployer = new ImageDeployer(ftpServer);
ImageDbSaver dbSaver = new ImageDbSaver(dbConnection, );
for(Image image : images) {
ImageProcessor p = new ImageResizer(desiredSize);
p.setNext(deployer);
p.setNext(dbSaver);
p.process(image);
}
dbSaver.close();
deployer.close();如果需要关闭ImageResizer,则需要某种方式来分离循环中的内容。
发布于 2013-08-01 08:52:50
如果性能没有问题,您将如何编写此代码?我认为为每个映像构建自定义处理器链是一个很好的解决方案,因为您似乎对每个映像都有不同的值。
现在,如果结果证明这太慢(这当然会发生),为什么不将一个DatabaseConnection和FtpConnection对象(在循环之外初始化)传递给需要这些对象的处理器呢?
https://stackoverflow.com/questions/17980648
复制相似问题