目前,我试图通过引入MVC模式来剖析应用程序中数据模型和UI之间的一些紧密耦合。基本上,这意味着让模型知道相关的视图,以便在模型内的属性发生变化时通知它们。
数据模型由嵌套结构表示:
Model
- Node
- Leaf
- Leaf
- Node
- Leaf
每个元素都继承自一个公共抽象基类(StructuredNode)。
我一直在考虑的问题是:观察者应该能够订阅模型(并且只能模型化),但每个元素都应该能够发出更改通知。这可以通过两种方式实现 - 通知在层次结构中路由,直到它们到达模型,在那里它们被推送到观察者,或者通过在基类中实现通知,使用静态观察者列表,如下例所示: / p>
public abstract class Base {
private static Map<IObserver> observers;
protected synchronized void internalSubscribe(final IObserver observer) {
observers.add(observer);
}
protected synchronized void notifyObservers(final Base obj) {
for (IObserver observer : observers)
observer.changed(obj);
}
// .. other base class operations
}
在此实现中,只有Model会提供一个公共订阅方法,该方法在内部委托给基类的受保护的internalSubscribe方法。同时,基类的每个派生都可以发送更改通知,如下所示:
// Perform some operations that change the object's internal state
// ...
// Then notify all observers
notifyObservers(this);
这是相当好的还是相当糟糕的做法(使用静态观察者列表)?有什么意见吗?有替代解决方案吗?
答案 0 :(得分:1)
静态观察者列表不是一种常见的解决方案,我不认为它是通用使用模型的好习惯。
观察员将被告知他们不感兴趣的模型的变化。这意味着识别触发通知的模型的所有负担都落在观察者身上,除了上升之外,这可能没有好的和有效的方法。层次结构和查找根节点...很多代码,必须在几个观察者中多次实现。最后,观察者更容易忽略注意事项,只更新或重新计算,即使更新的模型不是它感兴趣的模型。
当然,所有这些可能不适用于您的情况。如果您知道在您的应用程序中不会有多个此类的模型,那么您可以很好地使用此解决方案。
无论如何,只有具有公共订阅方法的Model的要求不应该限制您使用静态观察器容器在所有Model实例之间共享。正如你所说,还有另一种方式。将通知路由到层次结构是恕我直言,这是正确的方法。
如果您想避免路由,那么您可以选择让节点保持对其模型的引用。如果您知道树结构将是非常动态的,那么这可能会更有效。如果节点可以从一个模型移动到另一个模型,那么这有点风险,需要一些进一步的代码来保持参考更新。