在我的应用程序中,我有一个场景,如果特定模块发生更改,则必须通知其他几个模块。我认为观察者模式适合这里,通过保持作为主题发生变化的模块和作为观察者通知的模块。
但遵循观察者模式的原则,观察者彼此独立。观察者之间应该没有联系。就我而言,虽然模块不同,但它们依赖于模块。成功完成第一个模块的执行对于下一个执行模块很重要。此外,如果模块x发生故障,则必须还原模块1对模块x-1所做的所有更改。也就是说,要么所有模块都必须成功执行,要么我们必须回滚到以前的状态。你可以把它想象成一个交易。然后我意识到我错了观察者模式不是实现它的正确方法。
我有点坚持在这里想出一个干净的设计,其中有一组模块需要在主题发生变化时进行处理,但是在约束条件下模块相互依赖。有人可以帮我解决这个问题,想出一个好的设计吗?
答案 0 :(得分:1)
关于交易部分。实际上,你的问题是你正在对数据库执行一系列更新操作,而一个数据库的失败应该还原所有以前的操作。
天真的解决方案是简单地将原始呼叫包装在事务范围内。
开始交易 A: 更新数据库 举起活动 B: 更新数据库 举起活动 C:更新db 结束交易。
这可能会奏效!唯一的问题是,如果你之间的计算延长了交易的持续时间。交易应尽可能短,因此您需要确保在交易过程中不要“浪费”任何与交易资源无关的操作。
如果你有上述问题,你可以在一个地方累积所有更新命令(一个lambda表达式列表,每个表达式包含一个延迟执行到db) 并在所有更改累积后立即运行。
答案 1 :(得分:0)
您仍然可以使用观察者模式:您需要做的就是改变事件穿过观察者的方式。
在原始设计中,模块X引发并向模块A,B和C发出事件。但问题是C依赖于B,并且因为您不控制执行的顺序(并且不希望)观察者,你有一个问题。我建议你只做C和C的观察者,而不是A的观察者!
这样,当A引发事件时,它将以所需的顺序传播。 A - > B - > C.
话虽如此,我想知道你是否真的需要这种级别的解耦。基本上,您在此处描述了标准的信息流,除非模块非常可重用,否则您可以明确地进行调用。 A直接调用B,直接调用C。
事务是数据传播的正交问题。我担心你必须单独对待它们。如果您详细说明可能需要回滚的状态转换,社区也可能会尝试提供帮助。
答案 2 :(得分:0)
您可以为观察者使用Composite和获取 - 执行 - 释放结构。不知道我会不再称之为观察者 - 它更像是一个与复合相结合的交易抽象。
界面将是这样的:
public interface TransIf {
boolean acquire();
void execute() throws TransFailed;
void release();
}