Java:如何在添加模型集合时更新视图?

时间:2010-03-07 09:00:01

标签: java model-view-controller collections properties

所以我正在为教授重写一个程序,我有一些与模型 - 视图 - 控制器模式有关的问题。该程序称为GraphViewer,用于设计和查看图形(如图论,而不是统计)。到目前为止,我已经计划了这个结构:

  • 模型
    • VertexModel - 具有id,位置,颜色和与之重合的边集合
    • EdgeModel - 它有跨越的两个顶点,重量,颜色和其他一些东西
    • GraphModel - 主要但不仅仅是顶点集合和边集合
    • VertexView - 绘制其顶点,并具有自己的属性
    • EdgeView - 绘制其边缘,并且还具有一些自己的属性
    • GraphView - 基本上是一个具有顶点和边视图集合的JPanel,当它获取绘制命令时,它还遍历每个视图集并向它们发出绘制命令
  • 控制器
    • GraphController - 负责解释用户手势以添加顶点,边缘等,并更新模型。

现在我的第一个问题与此计划有关:每个模型都应该有一个视图 - 即使只有graphmodel是一个JComponent吗?现在我的一部分说是 - 因为每个顶点和边缘可能会有不同的绘制。但是我的另一部分对于graphview的那种并行列表结构没有尖叫,这些结构具有与graphview的graphmodel(复杂的男孩)的集合中的模型相对应的视图集合。不知何故,我必须努力,如果顶点或边缘模型发生变化,整个graphview必须重新绘制。我想这个答案也与每个模型是否都有一个控制器有关。 (我只是接近这个错误吗?)

第一个问题的答案与我的第二个问题紧密相关:如果将vertexmodel添加到graphmodel的集合中,我将如何知道通知graphview?如果设置了一个全新的集合,它将在进入setEdges()方法时通知视图。但是如果我必须写getEdges()。add(...)怎么办?现在需要通知graphview更新,但从未调用setEdges ...

非常感谢,因为你可以说我对设计模式有点新意!

3 个答案:

答案 0 :(得分:0)

不要公开模型的私有Collection成员,因此不允许调用getEdges()。add(...)

相反,公开API以允许添加/删除边缘,然后您可以使用Observer模式在模型更改时通知视图。

简单地说,只处理边缘......

public class EdgeModel extends AbstractCollection<Edge> implements Observable {
    private List<Edge> edges = new ArrayList<Edge>();
    @Override public Iterator<Edge> iterator() { return edges.iterator(); }
    @Override public int size() { return edges.size(); }
    @Override public boolean add(Edge edge) {
        if (edges.add(edge)) {
            this.notifyObservers();
            return true;
        }
        return false;
    }

    // other stuff for Observable
}

public class EdgeView implements Observer {
    public void setModel(EdgeModel model) {
        model.addObserver(this);
    }
    public void update(Observable o, Object arg) {
        // model o has changed... update something visual I guess
    }
}

答案 1 :(得分:0)

  1. 将视图附加到特定模型当且仅当需要以不同方式显示该模型时。对我而言,视图应该彼此独立,并且视图的层次结构听起来是错误的。如果您只在一个视图中显示模型,则单个GraphView就足够了。

  2. 您可以为您的集合编写一个包装器,它拦截所有修改调用以处理对其侦听器的必要修改。或者,您可以将GraphModel实现为Facade,其中包含整个图模型以实现相同的效果。

答案 2 :(得分:0)

首先,看看this question(及其答案)。它讨论了类似的问题。

其次,这里有一些关于你的问题的想法

  • 我觉得你对MVC有点过于教条。如果一个视图(即:GraphView)满足您的需求,则不必引入每个实体视图。
  • 似乎你的第二个问题假设getEdges()返回一个古老的java.util.List(或类似的东西)。为什么不在调用add()时引入自己的能够触发通知(到视图/控制器)的列表?
  • 最后,我会采用不同的方法:集中数据。 Edge,Graph类不是将数据封装在单个Vertex内,而是具有中央数据结构(例如,作为边缘列表)。此数据结构将在更改时触发通知。您仍然可以使用Edge和Vertex类,但这将不再是持久性实体。它们将是围绕中央数据结构的简单服务,允许您使用更高级别的接口来操纵顶点/边缘。