理解並使用設計模式,能夠培養我們良好的面向物件編程習慣,同時在實際應用中,可以如魚得水,享受遊刃有餘的樂趣。
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 {
/** * Permission to read object. */ public static final int READ = 0;
/** * Permission to administer the entire sytem. */ public static final int SYSTEM_ADMIN = 1;
/** * Permission to administer a particular forum. */ public static final int FORUM_ADMIN = 2;
/** * Permission to administer a particular user. */ public static final int USER_ADMIN = 3;
/** * Permission to administer a particular group. */ public static final int GROUP_ADMIN = 4;
/** * Permission to moderate threads. */ public static final int MODERATE_THREADS = 5;
/** * Permission to create a new thread. */ public static final int CREATE_THREAD = 6;
/** * Permission to create a new message. */ public static final int CREATE_MESSAGE = 7;
/** * Permission to moderate messages. */ public static final int MODERATE_MESSAGES = 8;
.....
public boolean isSystemOrForumAdmin() { return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]); }
.....
}
|
因此,Forum中各種操作許可權是和ForumPermissions定義的用戶級別有關係的,作爲介面Forum的實現:ForumProxy正是將這種對應關係聯繫起來。比如,修改Forum的名稱,只有論壇管理者或系統管理者可以修改,代碼如下:
public class ForumProxy implements Forum {
private ForumPermissions permissions; private Forum forum; this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization, ForumPermissions permissions) { this.forum = forum; this.authorization = authorization; this.permissions = permissions; }
.....
public void setName(String name) throws UnauthorizedException, ForumAlreadyExistsException { //只有是系統或論壇管理者才可以修改名稱 if (permissions.isSystemOrForumAdmin()) { forum.setName(name); } else { throw new UnauthorizedException(); } }
...
}
|
而DbForum才是介面Forum的真正實現,以修改論壇名稱爲例:
public class DbForum implements Forum, Cacheable { ...
public void setName(String name) throws ForumAlreadyExistsException {
....
this.name = name; //這裏真正將新名稱保存到資料庫中 saveToDb();
.... }
...
}
|
凡是涉及到對論壇名稱修改這一事件,其他程式都首先得和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; protected Authorization authorization; protected ForumPermissions permissions;
public ForumFactoryProxy(Authorization authorization, ForumFactory factory, ForumPermissions permissions) { this.factory = factory; this.authorization = authorization; this.permissions = permissions; }
public Forum createForum(String name, String description) throws UnauthorizedException, ForumAlreadyExistsException { //只有系統管理者才可以創建forum if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) { Forum newForum = factory.createForum(name, description); return new ForumProxy(newForum, authorization, permissions); } else { throw new UnauthorizedException(); } }
|
方法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模式的應用。
分享到:
相关推荐
设计模式C++学习之代理模式(Proxy)
Android设计模式之代理模式(Proxy Pattern)
为其他对象提供一个代理以控制对这个对象的访问。
代码仅供参考学习 。
设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...
详解设计模式中的proxy代理模式及在Java程序中的实现共14页.pdf.zip
java 代理模式实现代码及设计详解:动态代理模式、静态代理模式
NULL 博文链接:https://wy649898543.iteye.com/blog/1431997
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)
设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)
设计模式专题,代理模式,工厂模式
C++设计模式课件15_Proxy_代理模式.pdf
结构模式:设计模式之Facade(外观),设计模式之Proxy(代理),设计模式之Adapter(适配器),设计模式之Composite(组合),设计模式之Decorator(油漆工),设计模式之Bridge,设计模式之Flyweight(享元). 行为模式:设计模式之...
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要资源... 这是第13节:结构型模式Proxy代理模式
NULL 博文链接:https://lym6520.iteye.com/blog/692896
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
全部高质量代理模式proxy的java源程序 java.proxy,代理模式源码,设计模式,apache开源项目源码commons-proxy-1.0-src 各种代理模式操作的工具类源码以及代理模式案例源码,你会从中得到意想不到的效果! apache...
java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...