2010-03-07 103 views
2

所以我正在爲一位教授重寫一個程序,並且我有一些與Model-View-Controller模式有關的問題。該程序被稱爲GraphViewer,用於設計和查看圖形(如圖論中的統計)。到目前爲止,我已經打算這樣結構:Java:如何在模型集合添加到時更新視圖?

  • 模型
    • VertexModel - 擁有ID,位置,顏色和邊緣的集合是重合
    • EdgeModel - 有兩個頂點它跨越,重量,顏色,和幾個其他的事情
    • 而GraphModel - 主要是,但不僅僅是,頂點集合和邊集合
  • 瀏覽
    • VertexView - 繪製它的頂點,並擁有自己的屬性
    • EdgeView - 繪製它的邊緣,也有自身的一些特性
    • GraphView - 基本上一個JPanel具有的頂點和邊視圖的集合,當它到達一個繪圖指令,它也通過的意見和問題,每個集合迭代油漆命令將它們
  • 控制器
    • GraphController - 照顧Ø f解釋用戶手勢以添加頂點,邊等,並更新模型。

現在的第一個問題我已經是與此相關的計劃:如果每個模型有一個觀點 - 即使只向GraphModel是一個JComponent?現在我的一部分是說 - 是因爲每個頂點和邊緣可能繪製不同。但是我的另一部分人對圖表視圖類型的並行列表結構尖叫,該結構具有與graphview的graphmodel(複雜的男孩)的集合中的模型相對應的視圖集合。不知何故,我必須研究如果頂點或邊緣模型改變,整個graphview必須重繪。我想這個答案也與每個模型是否有控制器有關。 (我剛剛接近這個錯誤嗎?)

第一個問題的答案有點與我的第二個問題有關:我將如何知道通知graphview是否將一個vertexmodel添加到graphmodel的集合中?如果設置了一個全新的集合,它將在它進入setEdges()方法時通知視圖。但是如果我必須編寫getEdges()。add(...)呢?現在圖形視圖需要通知更新,但setEdges從未被稱爲...

感謝一堆,因爲你可以告訴我有點新的設計模式!

回答

0

不要暴露模型的私人收藏成員,因此不允許調用如getEdges()。添加(...)

相反,暴露一個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 
    } 
} 
+0

啊,有趣。所以你會有一個GraphModel,EdgeModel有Edge和VertexModel有Vertices?那麼GraphView是否有EdgeView和VertexView?另外,如果我們確定GraphView更新,例如Vertex的位置發生了變化,我該如何確定?對於所有僅僅獲取值的重寫方法(比如iterator()和size()),這似乎就是很多不必要的代碼。這是否意味着我永遠不會暴露可變對象(如Vertex中的Point2D和Edge中的Arc2D)? – 0x24a537r9 2010-03-07 09:43:10

+0

另外,我不會遇到與實現迭代器()相同的問題?然後,您可以編輯其中一個元素,而不會更新。現在,這對於一系列觀察對象來說不是問題,但是當我爲Edge封裝Arc2D類時呢?我有一個getPathIterator方法。我只是擔心如果每個類的每個部分都必須通知更新,我會卡在Java API中包裝所有內容以實現可觀察性。 – 0x24a537r9 2010-03-07 23:54:40

0
  1. 連接着眼於一個特定的模型當且僅當你需要不同的顯示模式。對我而言,觀點應該是彼此獨立的,觀點的層次結構聽起來是錯誤的。如果您只在一個視圖中顯示模型,則只需一個GraphView即可。

  2. 你可以爲你的集合編寫一個包裝器,它攔截所有修改調用以處理對其聽衆的必要修改。或者,您可以實現GraphModel作爲Facade,它將整個圖形模型包裝在內部以實現相同的效果。

+0

是的,觀點的層次結構確實聽起來很可疑。我猜想#2讓我問到同樣的問題,我問了ptomli,即MVC是否意味着我永遠不會暴露可變對象(如Vertex中的Point2D和Edge中的Arc2D)?爲每個可變對象編寫包裝並不是最好的方法。 – 0x24a537r9 2010-03-07 09:48:00

+0

@ 0x24a537r9因爲您想知道模型數據何時更改,您必須以某種方式將您的代碼包裹在模型數據中以處理此問題。我同意Facade方法更簡單。 – 2010-03-07 10:09:05

0

首先,看看this question(及其答案)。它討論了類似的問題。

其次,這裏有關於你的問題

  • 我感覺你有點過於教條關於MVC的一些想法。如果一個視圖(即:GraphView)滿足您的需求,則不一定要引入每個實體視圖。
  • 看來你的第二個問題是假設getEdges()返回一個古老的java.util.List(或類似的東西)。爲什麼不介紹自己的列表,只要調用add()就能觸發通知(到視圖/控制器)?
  • 最後,我會採用不同的方法:集中數據。而不是將數據封裝在單個Vertex,Edge,Graph類中的中央數據結構(例如,作爲邊的列表)。該數據結構將在更改時觸發通知。你仍然可以有Edge和Vertex類,但是這將不再是持久化實體。它們將是圍繞中心數據結構的簡單服務,允許您使用某個更高級別的界面來操作頂點/邊緣。
+0

我想我可能對MVC太過於教條 - 很高興知道我可以放鬆一點。那麼我應該讓GraphView管理繪製每個頂點和邊,並保存每個人的視圖屬性(例如,是否選擇了一個)? 至於你的第三個子彈,我不確定我是否理解。你是否說要廢棄VertexView和EdgeView,並分別將VertexModel和EdgeModel分別降級到Vertex和Edge類? – 0x24a537r9 2010-03-07 09:55:53

+0

我剛剛修復了第一句話中缺失的鏈接。 「GraphView管理繪圖...」聽起來很合理。它確實可以管理諸如已選,顏色等屬性。 關於第3個項目符號。我不是在講名字。我想說的是,一種可能的方法是讓GraphModel管理每一塊數據(關於邊,頂點和圖)。每個頂點將有一個ID。然後,您可以創建一個包含兩個字段的頂點類:vertexId,GraphModel。這樣的類將允許您通過面向頂點的界面操作頂點。 – 2010-03-07 10:01:51