文章詳情頁(yè)
java設(shè)計(jì)模式之Proxy(代理)
瀏覽:11日期:2024-06-30 13:17:18
內(nèi)容: 理解并使用設(shè)計(jì)模式,能夠培養(yǎng)我們良好的面向?qū)ο缶幊塘?xí)慣,同時(shí)在實(shí)際應(yīng)用中,可以如魚得水,享受游刃有余的樂(lè)趣.Proxy是比較有用途的一種模式,而且變種較多,應(yīng)用場(chǎng)合覆蓋從小結(jié)構(gòu)到整個(gè)系統(tǒng)的大結(jié)構(gòu),Proxy是代理的意思,我們也許有代理服務(wù)器等概念,代理概念可以解釋為:在出發(fā)點(diǎn)到目的地之間有一道中間層,意為代理.設(shè)計(jì)模式中定義: 為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn).為什么要使用Proxy?1.授權(quán)機(jī)制 不同級(jí)別的用戶對(duì)同一對(duì)象擁有不同的訪問(wèn)權(quán)利,如Jive論壇系統(tǒng)中,就使用Proxy進(jìn)行授權(quán)機(jī)制控制,訪問(wèn)論壇有兩種人:注冊(cè)用戶和游客(未注冊(cè)用戶),Jive中就通過(guò)類似ForumProxy這樣的代理來(lái)控制這兩種用戶對(duì)論壇的訪問(wèn)權(quán)限.2.某個(gè)客戶端不能直接操作到某個(gè)對(duì)象,但又必須和那個(gè)對(duì)象有所互動(dòng).舉例兩個(gè)具體情況: (1)如果那個(gè)對(duì)象是一個(gè)是很大的圖片,需要花費(fèi)很長(zhǎng)時(shí)間才能顯示出來(lái),那么當(dāng)這個(gè)圖片包含在文檔中時(shí),使用編輯器或?yàn)g覽器打開這個(gè)文檔,打開文檔必須很迅速,不能等待大圖片處理完成,這時(shí)需要做個(gè)圖片Proxy來(lái)代替真正的圖片.(2)如果那個(gè)對(duì)象在Internet的某個(gè)遠(yuǎn)端服務(wù)器上,直接操作這個(gè)對(duì)象因?yàn)榫W(wǎng)絡(luò)速度原因可能比較慢,那我們可以先用Proxy來(lái)代替那個(gè)對(duì)象.總之原則是,對(duì)于開銷很大的對(duì)象,只有在使用它時(shí)才創(chuàng)建,這個(gè)原則可以為我們節(jié)省很多寶貴的Java內(nèi)存. 所以,有些人認(rèn)為Java耗費(fèi)資源內(nèi)存,我以為這和程序編制思路也有一定的關(guān)系.如何使用Proxy?以Jive論壇系統(tǒng)為例,訪問(wèn)論壇系統(tǒng)的用戶有多種類型:注冊(cè)普通用戶 論壇管理者 系統(tǒng)管理者 游客,注冊(cè)普通用戶才能發(fā)言;論壇管理者可以管理他被授權(quán)的論壇;系統(tǒng)管理者可以管理所有事務(wù)等,這些權(quán)限劃分和管理是使用Proxy完成的.Forum是Jive的核心接口,在Forum中陳列了有關(guān)論壇操作的主要行為,如論壇名稱 論壇描述的獲取和修改,帖子發(fā)表刪除編輯等.在ForumPermissions中定義了各種級(jí)別權(quán)限的用戶: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中各種操作權(quán)限是和ForumPermissions定義的用戶級(jí)別有關(guān)系的,作為接口Forum的實(shí)現(xiàn):ForumProxy正是將這種對(duì)應(yīng)關(guān)系聯(lián)系起來(lái).比如,修改Forum的名稱,只有論壇管理者或系統(tǒng)管理者可以修改,代碼如下: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{//只有是系統(tǒng)或論壇管理者才可以修改名稱if (permissions.isSystemOrForumAdmin()) {forum.setName(name);}else {throw new UnauthorizedException();}}...} 而DbForum才是接口Forum的真正實(shí)現(xiàn),以修改論壇名稱為例:public class DbForum implements Forum, Cacheable {...public void setName(String name) throws ForumAlreadyExistsException {....this.name = name;//這里真正將新名稱保存到數(shù)據(jù)庫(kù)中 saveToDb();....}... } 凡是涉及到對(duì)論壇名稱修改這一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy決定是否有權(quán)限做某一樣事情,ForumProxy是個(gè)名副其實(shí)的'網(wǎng)關(guān)','安全代理系統(tǒng)'.在平時(shí)應(yīng)用中,無(wú)可避免總要涉及到系統(tǒng)的授權(quán)或安全體系,不管你有無(wú)意識(shí)的使用Proxy,實(shí)際你已經(jīng)在使用Proxy了.我們繼續(xù)結(jié)合Jive談入深一點(diǎn),下面要涉及到工廠模式了,如果你不了解工廠模式,請(qǐng)看我的另外一篇文章:設(shè)計(jì)模式之Factory我們已經(jīng)知道,使用Forum需要通過(guò)ForumProxy,Jive中創(chuàng)建一個(gè)Forum是使用Factory模式,有一個(gè)總的抽象類ForumFactory,在這個(gè)抽象類中,調(diào)用ForumFactory是通過(guò)getInstance()方法實(shí)現(xiàn),這里使用了Singleton(也是設(shè)計(jì)模式之一,由于介紹文章很多,我就不寫了,看這里),getInstance()返回的是ForumFactoryProxy.為什么不返回ForumFactory,而返回ForumFactory的實(shí)現(xiàn)ForumFactoryProxy?原因是明顯的,需要通過(guò)代理確定是否有權(quán)限創(chuàng)建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{//只有系統(tǒng)管理者才可以創(chuàng)建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交互操作.注意到這里有兩個(gè)Proxy:ForumProxy和ForumFactoryProxy. 代表兩個(gè)不同的職責(zé):使用Forum和創(chuàng)建Forum;至于為什么將使用對(duì)象和創(chuàng)建對(duì)象分開,這也是為什么使用Factory模式的原因所在:是為了'封裝' '分派';換句話說(shuō),盡可能功能單一化,方便維護(hù)修改.Jive論壇系統(tǒng)中其他如帖子的創(chuàng)建和使用,都是按照Forum這個(gè)思路而來(lái)的.以上我們討論了如何使用Proxy進(jìn)行授權(quán)機(jī)制的訪問(wèn),Proxy還可以對(duì)用戶隱藏另外一種稱為copy-on-write的優(yōu)化方式.拷貝一個(gè)龐大而復(fù)雜的對(duì)象是一個(gè)開銷很大的操作,如果拷貝過(guò)程中,沒(méi)有對(duì)原來(lái)的對(duì)象有所修改,那么這樣的拷貝開銷就沒(méi)有必要.用代理延遲這一拷貝過(guò)程.比如:我們有一個(gè)很大的Collection,具體如hashtable,有很多客戶端會(huì)并發(fā)同時(shí)訪問(wèn)它.其中一個(gè)特別的客戶端要進(jìn)行連續(xù)的數(shù)據(jù)獲取,此時(shí)要求其他客戶端不能再向hashtable中增加或刪除 東東.最直接的解決方案是:使用collection的lock,讓這特別的客戶端獲得這個(gè)lock,進(jìn)行連續(xù)的數(shù)據(jù)獲取,然后再釋放lock.public void foFetches(Hashtable ht){synchronized(ht){//具體的連續(xù)數(shù)據(jù)獲取動(dòng)作.. } }但是這一辦法可能鎖住Collection會(huì)很長(zhǎng)時(shí)間,這段時(shí)間,其他客戶端就不能訪問(wèn)該Collection了.第二個(gè)解決方案是clone這個(gè)Collection,然后讓連續(xù)的數(shù)據(jù)獲取針對(duì)clone出來(lái)的那個(gè)Collection操作.這個(gè)方案前提是,這個(gè)Collection是可clone的,而且必須有提供深度clone的方法.Hashtable就提供了對(duì)自己的clone方法,但不是Key和value對(duì)象的clone,關(guān)于Clone含義可以參考專門文章.public void foFetches(Hashtable ht){Hashttable newht=(Hashtable)ht.clone();}問(wèn)題又來(lái)了,由于是針對(duì)clone出來(lái)的對(duì)象操作,如果原來(lái)的母體被其他客戶端操作修改了, 那么對(duì)clone出來(lái)的對(duì)象操作就沒(méi)有意義了.最后解決方案:我們可以等其他客戶端修改完成后再進(jìn)行clone,也就是說(shuō),這個(gè)特別的客戶端先通過(guò)調(diào)用一個(gè)叫clone的方法來(lái)進(jìn)行一系列數(shù)據(jù)獲取操作.但實(shí)際上沒(méi)有真正的進(jìn)行對(duì)象拷貝,直至有其他客戶端修改了這個(gè)對(duì)象Collection.使用Proxy實(shí)現(xiàn)這個(gè)方案.這就是copy-on-write操作.Proxy應(yīng)用范圍很廣,現(xiàn)在流行的分布計(jì)算方式RMI和Corba等都是Proxy模式的應(yīng)用.更多Proxy應(yīng)用,見http://www.research.umbc.edu/~tarr/cs491/lectures/Proxy.pdfSun公司的 Explore the Dynamic Proxy API Dynamic Proxy Classes Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
標(biāo)簽:
Java
相關(guān)文章:
1. JavaScript設(shè)計(jì)模式之策略模式實(shí)現(xiàn)原理詳解2. 《CSS3實(shí)戰(zhàn)》筆記--漸變?cè)O(shè)計(jì)(一)3. Java通俗易懂系列設(shè)計(jì)模式之責(zé)任鏈模式4. 《javascript設(shè)計(jì)模式》學(xué)習(xí)筆記五:Javascript面向?qū)ο蟪绦蛟O(shè)計(jì)工廠模式實(shí)例分析5. PHP設(shè)計(jì)模式概論【概念、分類、原則等】6. javascript設(shè)計(jì)模式 ? 備忘錄模式原理與用法實(shí)例分析7. java設(shè)計(jì)模式之Bridge8. JS中間件設(shè)計(jì)模式的深入探討與實(shí)例分析9. php設(shè)計(jì)模式之代理模式分析【星際爭(zhēng)霸游戲案例】10. PHP設(shè)計(jì)模式(一)工廠模式Factory實(shí)例詳解【創(chuàng)建型】
排行榜
