0

在我的应用程序中,我有一个场景,如果特定模块发生更改,则必须将其通知给其他几个模块。我认为观察者模式适合这里,通过将发生更改的模块保持为主题并将要通知的模块作为观察者。

但是按照观察者模式的原则,观察者是相互独立的。观察者之间不应该有任何联系。就我而言,尽管模块不同,但它们是相互依赖的。成功完成第一个模块的执行对于下一个要执行的模块很重要。此外,如果模块 x 发生故障,则必须恢复模块 1 对模块 x-1 所做的所有更改。也就是说,要么所有模块都必须成功执行,要么我们必须回滚到以前的状态。你可以把它想象成一个交易。然后我意识到我错了,观察者模式不是实现这一点的正确方法。

我有点想提出一个干净的设计,其中有一组模块需要在主题发生变化时进行处理,但在约束条件下,模块相互依赖。有人可以帮我解决这个问题以提出一个好的设计吗?

4

3 回答 3

1

关于交易部分。实际上,您的问题是您正在对数据库执行一系列更新操作,并且一个失败应该恢复以前的所有操作。

天真的解决方案是简单地将原始调用包装在事务范围内。

开始事务 A:更新数据库引发事件 B:更新数据库引发事件 C:更新数据库结束事务。

这可能会奏效!唯一的问题是,如果您在两者之间进行计算,则会延长事务的持续时间。事务应尽可能短,因此您需要确保在事务期间不会“浪费”任何时间在与事务下的资源无关的操作上。

如果您有上述问题,您可以将所有更新命令累积在一个地方(一个 lambda 表达式列表,每个都将延迟执行包装到 db)并在累积所有更改后立即运行它们。

于 2012-08-09T07:43:02.000 回答
0

您仍然可以使用观察者模式:您需要做的就是改变事件在观察者之间传播的方式。

在最初的设计中,模块 X 引发了模块 A、B 和 C 的事件。但问题是 C 依赖于 B,并且由于您无法控制(也不想)观察者的执行顺序, 你有问题。我建议你简单地让 C 和 B 的观察者,而不是 A 的观察者!

这样,当 A 引发事件时,它将以所需的顺序传播。A -> B -> C。

话虽如此,我想知道您是否真的需要这种程度的解耦。基本上,您在这里描述的是标准的信息流,除非模块非常可重用,否则您可以显式地进行调用。A直接调用B,B直接调用C。

事务是数据传播的正交关注点。恐怕您将不得不分别对待它们。如果您详细说明可能需要回滚的状态转换,社区也可能会尝试提供帮助。

于 2012-08-09T05:44:01.770 回答
0

你可以为你的观察者使用 Composite 和一个获取-执行-释放结构。不过,我不确定我会不再称它为观察者——它更像是事务与复合的抽象。

界面将是这样的:

public interface TransIf {
  boolean acquire();
  void execute() throws TransFailed;
  void release();
}
于 2012-08-09T08:46:48.283 回答