【发布时间】:2010-10-29 12:33:10
【问题描述】:
假设您有一个包含两层的应用程序:
- 答:存储从数据库或文件加载的所有数据的数据层
- B:在漂亮的用户界面中显示数据的层,例如图形报告
现在,A 层中的数据发生了变化。我们有 2 种方法来确保正确更新 B 层的报告。
第一种方法是 PUSH 方法。 A 层通过观察者通知 B 层,因此 B 层可以更新其报告。
PUSH 方法有几个缺点:
- 如果数据被多次更改(例如,在加载期间或在更改大量数据的算法中),观察者会被执行多次。这可以通过引入一种缓冲来解决(防止在您仍在更改时调用观察者),但这可能非常棘手,并且经常忘记进行正确的缓冲调用。
- 如果更改了大量数据,观察者调用可能会导致应用程序无法接受的开销。
另一种方法是 PULL 方法。 A 层只记住哪些数据被更改并且不发送任何通知(A 层被标记为脏)。在用户执行操作(可能是运行算法或加载文件或其他)之后,我们检查所有用户界面组件,并要求它们自行更新。 在这种情况下,层 B 被要求更新自身。首先,它将检查其任何底层(A 层)是否脏。如果是,它将获取更改并自行更新。如果 A 层不脏,则报告知道它无事可做。
最佳解决方案取决于具体情况。在我的情况下,PUSH 方法似乎要好得多。
如果我们有超过 2 层,情况会变得更加困难。假设我们有以下 4 层:
- 答:存储从数据库或文件加载的所有数据的数据层
- B:使用数据层(A 层)的层,例如使用复杂的过滤函数过滤来自 A 的数据
- C:使用 B 层的层,例如将 B 层的数据聚合成更小的信息片段
- D:解释 C 层结果并以精美的图形方式向用户呈现的报告
在这种情况下,推送更改几乎肯定会引入更高的开销。
另一方面,拉取更改需要:
- D 层必须调用 C 层来询问它是否脏
- C 层必须调用 B 层询问是否脏
- B 层必须调用 A 层来询问它是否脏
如果什么都没有改变,那么在你知道实际上什么都没有改变并且你不需要做任何事情之前执行的调用量是相当大的。看起来我们试图通过不使用 PUSH 来避免的性能开销,现在又重新用于 PULL 方法,因为有很多电话询问是否有任何脏东西。
是否存在以良好且高性能(低开销)的方式解决此类问题的模式?
【问题讨论】:
标签: design-patterns language-agnostic architecture