理解並使用設計模式 , 能夠培養我們良好的面向物件編程習慣 , 同時在實際應用中 , 可以如魚得水 , 享受遊刃有餘的樂趣。
Proxy 是比較有用途的一種模式 , 而且變種較多 , 應用場合覆蓋從小結構到整個系統的大結構 ,Proxy 是代理的意思 , 我們也許有代理伺服器等概念 , 代理概念可以解釋爲 : 在出發點到目的地之間有一道中間層 , 意爲代理。
設計模式中定義 : 爲其他物件提供一種代理以控制對這個物件的訪問。
爲什麽要使用
Proxy?
1.
授權機制
不同級別的用戶對同一物件擁有不同的訪問權利
,
如
Jive
論壇系統中
,
就使用
Proxy
進行授權機制控制
,
訪問論壇有兩種人
:
註冊用戶和遊客
(
未註冊用戶
),Jive
中就通過類似
ForumProxy
這樣的代理來控制這兩種用戶對論壇的訪問許可權。
2.
某個用戶端不能直接操作到某個物件
,
但又必須和那個物件有所互動。
舉例兩個具體情況
:
(1)
如果那個物件是一個是很大的圖片
,
需要花費很長時間才能顯示出來
,
那麽當這個圖片包含在文檔中時
,
使用編輯器或瀏覽器打開這個文檔
,
打開文檔必須很迅速
,
不能等待大圖片處理完成
,
這時需要做個圖片
Proxy
來代替真正的圖片。
(2)
如果那個物件在
Internet
的某個遠端伺服器上
,
直接操作這個物件因爲網路速度原因可能比較慢
,
那我們可以先用
Proxy
來代替那個物件。
總之原則是 , 對於開銷很大的物件 , 只有在使用它時才創建 , 這個原則可以爲我們節省很多寶貴的 Java 記憶體。 所以 , 有些人認爲 Java 耗費資源記憶體 , 我以爲這和程式編制思路也有一定的關係。
如何使用
Proxy?
以
Jive論壇系統
爲例
,
訪問論壇系統的用戶有多種類型
:
註冊普通用戶
論壇管理者
系統管理者
遊客
,
註冊普通用戶才能發言
;
論壇管理者可以管理他被授權的論壇
;
系統管理者可以管理所有事務等
,
這些許可權劃分和管理是使用
Proxy
完成的。
Forum 是 Jive 的核心介面 , 在 Forum 中陳列了有關論壇操作的主要行爲 , 如論壇名稱 論壇描述的獲取和修改 , 帖子發表刪除編輯等。
在 ForumPermissions 中定義了各種級別許可權的用戶 :
|
public class ForumPermissions implements Cacheable { /** /** /** /** /** /** /** /** /** ..... public boolean isSystemOrForumAdmin() { ..... } |
因此 ,Forum 中各種操作許可權是和 ForumPermissions 定義的用戶級別有關係的 , 作爲介面 Forum 的實現 :ForumProxy 正是將這種對應關係聯繫起來。比如 , 修改 Forum 的名稱 , 只有論壇管理者或系統管理者可以修改 , 代碼如下 :
|
public class ForumProxy implements Forum {
private ForumPermissions permissions; public void setName(String name) throws UnauthorizedException, ... } |
而 DbForum 才是介面 Forum 的真正實現 , 以修改論壇名稱爲例 :
|
public class DbForum implements Forum, Cacheable { ... public void setName(String name) throws ForumAlreadyExistsException {
....
} |
凡是涉及到對論壇名稱修改這一事件 , 其他程式都首先得和 ForumProxy 打交道 , 由 ForumProxy 決定是否有許可權做某一樣事情 ,ForumProxy 是個名副其實的 " 閘道 "," 安全代理系統 " 。
在平時應用中 , 無可避免總要涉及到系統的授權或安全體系 , 不管你有無意識的使用 Proxy, 實際你已經在使用 Proxy 了。
我們繼續結合 Jive 談入深一點 , 下面要涉及到工廠模式了 , 如果你不瞭解工廠模式 , 請看我的另外一篇文章 :設計模式之 Factory
我們已經知道 , 使用 Forum 需要通過 ForumProxy,Jive 中創建一個 Forum 是使用 Factory 模式 , 有一個總的抽象類別 ForumFactory, 在這個抽象類別中 , 呼叫 ForumFactory 是通過 getInstance() 方法實現 , 這裏使用了 Singleton( 也是設計模式之一 , 由於介紹文章很多 , 我就不寫了 ,看這裏 ),getInstance() 返回的是 ForumFactoryProxy 。
爲什麽不返回
ForumFactory,
而返回
ForumFactory
的實現
ForumFactoryProxy?
原因是明顯的
,
需要通過代理確定是否有許可權創建
forum
。
在 ForumFactoryProxy 中我們看到代碼如下 :
|
public class ForumFactoryProxy extends ForumFactory {
protected ForumFactory factory;
public ForumFactoryProxy(Authorization authorization, ForumFactory factory,
public Forum createForum(String name, String description) |
方法 createForum 返回的也是 ForumProxy, Proxy 就象一道牆 , 其他程式只能和 Proxy 交互操作。
注意到這裏有兩個
Proxy:ForumProxy
和
ForumFactoryProxy
。
代表兩個不同的職責
:
使用
Forum
和創建
Forum;
至於爲什麽將使用物件和創建物件分開
,
這也是爲什麽使用
Factory
模式的原因所在
:
是爲了
"
封裝
" "
分派
";
換句話說
,
盡可能功能單一化
,
方便維護修改。
Jive 論壇系統中其他如帖子的創建和使用 , 都是按照 Forum 這個思路而來的。
以上我們討論了如何使用 Proxy 進行授權機制的訪問 ,Proxy 還可以對用戶隱藏另外一種稱爲 copy-on-write 的優化方式。拷貝一個龐大而複雜的物件是一個開銷很大的操作 , 如果拷貝過程中 , 沒有對原來的物件有所修改 , 那麽這樣的拷貝開銷就沒有必要。用代理延遲這一拷貝過程。
比如 : 我們有一個很大的 Collection, 具體如 hashtable, 有很多用戶端會並發同時訪問它。其中一個特別的用戶端要進行連續的資料獲取 , 此時要求其他用戶端不能再向 hashtable 中增加或刪除 東東。
最直接的解決方案是
:
使用
collection
的
lock,
讓這特別的用戶端獲得這個
lock,
進行連續的資料獲取
,
然後再釋放
lock
。
public void foFetches(Hashtable ht){
synchronized(ht){
//
具體的連續資料獲取動作。。
}
}
但是這一辦法可能鎖住 Collection 會很長時間 , 這段時間 , 其他用戶端就不能訪問該 Collection 了。
第二個解決方案是
clone
這個
Collection,
然後讓連續的資料獲取針對
clone
出來的那個
Collection
操作。這個方案前提是
,
這個
Collection
是可
clone
的
,
而且必須有提供深度
clone
的方法。
Hashtable
就提供了對自己的
clone
方法
,
但不是
Key
和
value
物件的
clone,
關於
Clone
含義可以參考
專門文章
。
public void foFetches(Hashtable ht){
Hashttable newht=(Hashtable)ht.clone();
}
問題又來了 , 由於是針對 clone 出來的物件操作 , 如果原來的母體被其他用戶端操作修改了 , 那麽對 clone 出來的物件操作就沒有意義了。
最後解決方案 : 我們可以等其他用戶端修改完成後再進行 clone, 也就是說 , 這個特別的用戶端先通過呼叫一個叫 clone 的方法來進行一系列資料獲取操作。但實際上沒有真正的進行物件拷貝 , 直至有其他用戶端修改了這個物件 Collection 。
使用 Proxy 實現這個方案。這就是 copy-on-write 操作。
Proxy 應用範圍很廣 , 現在流行的分佈計算方式 RMI 和 Corba 等都是 Proxy 模式的應用。
本文深入探讨了设计模式中的Proxy模式,介绍了其应用场景包括权限控制和优化开销大的对象操作,并通过Jive论坛系统的实例详细解释了如何实现权限管理和Copy-on-write优化。
1439

被折叠的 条评论
为什么被折叠?



