2013-02-27 53 views
1

我想在邏輯部分'Data','Commands'和'Engines'中打破我的應用程序模型。應用程序外的所有人都應該獲得對數據的只讀訪問權限並訪問命令。利用這些命令,他們可以操縱數據。限制公共可訪問成員 - 解決方法

這個我已經sturctured在包我的應用程序:

myapp.model.data 
myapp.model.commands 
myapp.model.engines 

無論是發動機和命令,需要將數據進行寫訪問。因此我必須公開一個公共接口形式的寫權限。這導致了外部客戶端也可以對我的數據進行寫入訪問的問題,這是不允許的。這樣做的問題是,命令會調用引擎來檢查數據的一致性。客戶端會在不調用引擎的情況下操縱數據,從而破壞數據的一致性。

有沒有這個問題的共同實踐。請不要建議我必須等到Java 8,因爲我現在想寫我的應用程序。將所有類放在一個包中也是沒有選擇的,因爲我會丟失我的應用程序的概述。

編輯

我大約有樹木和圖表不變性一些網站閱讀。我見過一個叫拉鍊的好主意:http://scienceblogs.com/goodmath/2010/01/13/zippers-making-functional-upda/。不幸的是,這似乎不適用於我的情況。

回想一下,我有一個複雜的對象圖結構,它將隨着時間的推移而被操縱。目標是限制客戶端僅通過我的命令操作數據。所以我沒有看到我的情況下不變性的優點。

爲此,我給數據類兩個公共接口一個readonly一個可寫。每當客戶端使用只讀實例調用一個命令時,我只需將其轉換爲可寫實例。這方法解決了我的問題,但有兩大缺點。首先我假設每個只讀實例都是可寫實例,這可能會導致一些醜陋的錯誤。其次,客戶端可以做同樣的事情並擁有寫權限。但是,我可以說它是他們自己的錯。

有人更好的主意嗎?

回答

1

有是我爲這類問題而努力的三種模式。按照大概的順序,我嘗試他們:

1)去不變/副作用免費。一種被函數式編程語言強烈推薦的技術,而java.lang.String就是一個例子。這裏一個實例是不可變的,並且調用mutate創建一個新的實例。可能不適用於你如何爲你的命令和引擎設計接口,但如果你有能力重新設計他們的接口,那麼這是一個非常強大的方法,這往往會減少線數。

2)可鎖定的對象模式。一個對象在第一次創建時是可變的,但它在被共享之前被「鎖定」。被鎖定後,任何調用mutating方法的錯誤。解鎖對象涉及創建對象的新副本。

3)爲可變實例創建一個只讀包裝器。這允許您控制誰可以變異,誰可以只讀。 java.util.Collections#unmodifiableList(List list)是這個裝飾器樣式模式的Java運行時的一個例子,它保持共享接口上的setter方法。人們可以使用不同的接口,根本沒有setter方法。

我的偏好總是1,因爲它導致更簡單的代碼更易於擴展。但是,如果我遇到問題,那麼我傾向於回退到2,因爲它在方法之間提供了平衡,並且不允許另一個線程在另一個線程後面突變實例。它也不需要太多額外的代碼,但它確實需要紀律以確保對象正確鎖定並強制執行鎖定語義。因此在實踐中它不是一個非常常見的模式。

+0

我喜歡這個想法不可變類。這裏的問題是我的數據是樹形結構,並作爲用戶界面的數據源。我會研究這一點並嘗試找到一個好的解決方案。感謝你的回答。 – Yggdrasil 2013-02-27 10:16:33

+0

重新設計不可變數據結構可能會很棘手。 Clojure使用的模式由一個可以用於你的類型的散列樹支持。它涉及使用不可變的哈希映射來實現該樹。雖然可能在這裏殺了你,但它是一個有趣的閱讀。 http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/ – 2013-02-27 10:55:01

+0

這裏不變性的優勢是什麼。我的數據隨着時間而改變,因此不是不可變的。 – Yggdrasil 2013-02-27 11:23:04

1

我認爲這是文件夾(樹狀結構)的常見限制。 解決方案:

  1. 確保您不應訪問文檔數據(JavaDoc)。
  2. 如果你想要去的極致,你可以檢查其中呼叫是來自與否認(有點大材小用)

這裏作爲補充是關於這一主題的博客文章:A simple suggestion to radically improve your package structure

+0

這可能是可能的,但我所說的是一個解決方案,外部世界只能用命令操作數據。 – Yggdrasil 2013-02-27 10:18:46

+0

我想你已經知道可能的解決方案,閱讀此:http://stackoverflow.com/questions/403583/what-is-the-use-of-package-level-protection-in-java – 2013-02-27 10:24:39