首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >责任链模式-与后代紧密耦合

责任链模式-与后代紧密耦合
EN

Stack Overflow用户
提问于 2013-07-31 20:45:17
回答 3查看 292关注 0票数 2

我的问题是如何将操作放入链中,以便在操作处理过程中传递额外的参数。

让我们考虑简单的过程链。输入是一个表示图像的对象。首先调整映像的大小,然后将其部署到ftp并保存到db中。使用责任链模式,调用可能如下所示:

代码语言:javascript
复制
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和路径。我不能每次创建和关闭连接,因此必须传播代码:

代码语言:javascript
复制
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参数,比如大小和路径就没有意义了。

有什么更好的方法来做呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-31 21:16:57

我想,在您的情况下,最健壮的解决方案是添加某种处理上下文。

在最简单的情况下,您可以(1)为此使用(例如Map<String, Object> ),(2)用特定于各种处理器的参数包装它,(3)将它传递到p.process(...)中,(4)然后提取(例如,在调整图像大小的处理器中的size )。

这样,您就可以灵活地添加新的参数,而无需更改ImageProcessor的签名,并保持实现者之间的解耦。

类似的实际例子是Java中的请求\session\servlet上下文。您可以在不同的生命周期阶段(例如,关于urls应该需要什么的安全配置选项)将内容放入其中,然后在需要的地方获取这些东西(例如,在过滤器中阻止\允许基于auth需求访问资源)。

更新

用代码示例更新答案以演示这个想法。

因此,在代码中的某个地方,您可以构建处理器链:

代码语言:javascript
复制
ImageProcessor p = new ImageResizer(desiredSize);
p.setNext(new (new ImageDeployer(ftpServer, path)));
p.setNext(new (new ImageDbSaver(dbConnection, table)));

在(可能的)其他地方创建和配置处理上下文(并不需要在一个地方配置所有处理器):

代码语言:javascript
复制
Map<String, Object> context = new HashMap<String, Object>();
context.put("image_width", new Integer(640));

在代码中的另一个地方,您可以进行处理,将上下文传递给它(我在所有处理过程中重用上下文,但您可能对每个图像使用不同的上下文):

代码语言:javascript
复制
for(Image image : images) {
  p.process(image, context);
}
p.close();

现在,在ImageResizer的某个地方

代码语言:javascript
复制
@Override
void process(Image image, Map<String, Object> context) {

    // ...

    Integer imageWidth = (Integer) context.get("image_width");

    // ...

}

因此,上下文是一个常见的地方,它帮助将数据传递到特定的处理器,抽象出有关这些数据的详细信息,从而使特定处理器相互分离。

票数 2
EN

Stack Overflow用户

发布于 2013-07-31 21:30:30

一个简单的解决方法是在循环之外构造不变量。例如:

代码语言:javascript
复制
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,则需要某种方式来分离循环中的内容。

票数 0
EN

Stack Overflow用户

发布于 2013-08-01 08:52:50

如果性能没有问题,您将如何编写此代码?我认为为每个映像构建自定义处理器链是一个很好的解决方案,因为您似乎对每个映像都有不同的值。

现在,如果结果证明这太慢(这当然会发生),为什么不将一个DatabaseConnectionFtpConnection对象(在循环之外初始化)传递给需要这些对象的处理器呢?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17980648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档