23種設(shè)計(jì)模式--代理模式

前言:Proxy是比較有用途的一種模式,而且變種較多,應(yīng)用場(chǎng)合覆蓋從小結(jié)構(gòu)到整個(gè)系統(tǒng)的大結(jié)構(gòu),Proxy是代理的意思,我們也許有代理服務(wù)器等概念,代理概念可以解釋為:在出發(fā)點(diǎn)到目的地之間有一道中間層,意為代理。

1.代理模式的定義

代理(Proxy)是一種設(shè)計(jì)模式,提供了對(duì)目標(biāo)對(duì)象另外的訪問方式;即通過代理對(duì)象訪問目標(biāo)對(duì)象。這樣做的好處是:可以在目標(biāo)對(duì)象實(shí)現(xiàn)的基礎(chǔ)上,增強(qiáng)額外的功能操作,即擴(kuò)展目標(biāo)對(duì)象的功能。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式。


進(jìn)群:697699179可以獲取Java各類入門學(xué)習(xí)資料!

這是我的微信公眾號(hào)【編程study】各位大佬有空可以關(guān)注下,每天更新Java學(xué)習(xí)方法,感謝!

學(xué)習(xí)中遇到問題有不明白的地方,推薦加小編Java學(xué)習(xí)群:697699179內(nèi)有視頻教程 ,直播課程 ,等學(xué)習(xí)資料,期待你的加入

2.作用

中介隔離作用:

在某些情況下,一個(gè)客戶類不想或者不能直接引用一個(gè)委托對(duì)象,而代理類對(duì)象可以在客戶類和委托對(duì)象之間起到中介的作用,其特征是代理類和委托類實(shí)現(xiàn)相同的接口。

開閉原則,增加功能:

代理類除了是客戶類和委托類的中介之外,我們還可以通過給代理類增加額外的功能來擴(kuò)展委托類的功能,這樣做我們只需要修改代理類而不需要再修改委托類,符合代碼設(shè)計(jì)的開閉原則。代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后對(duì)返回結(jié)果的處理等。代理類本身并不真正實(shí)現(xiàn)服務(wù),而是同過調(diào)用委托類的相關(guān)方法,來提供特定的服務(wù)。真正的業(yè)務(wù)功能還是由委托類來實(shí)現(xiàn),但是可以在業(yè)務(wù)功能執(zhí)行的前后加入一些公共的服務(wù)。例如我們想給項(xiàng)目加入緩存、日志這些功能,我們就可以使用代理類來完成,而沒必要打開已經(jīng)封裝好的委托類。

3.優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1、職責(zé)清晰。

2、高擴(kuò)展性。

3、智能化。

缺點(diǎn):

1、由于在客戶端和真實(shí)主題之間增加了代理對(duì)象,因此有些類型的代理模式可能會(huì)造成請(qǐng)求的處理速度變慢。

2、實(shí)現(xiàn)代理模式需要額外的工作,有些代理模式的實(shí)現(xiàn)非常復(fù)雜。

4.代理模式的分類

如果按照代理創(chuàng)建的時(shí)期來進(jìn)行分類的話, 可以分為兩種:靜態(tài)代理、動(dòng)態(tài)代理。靜態(tài)代理是由程序員創(chuàng)建或特定工具自動(dòng)生成源代碼,在對(duì)其編譯。在程序員運(yùn)行之前,代理類.class文件就已經(jīng)被創(chuàng)建了;動(dòng)態(tài)代理是在程序運(yùn)行時(shí)通過反射機(jī)制動(dòng)態(tài)創(chuàng)建的。

5.代碼實(shí)現(xiàn)

5.1靜態(tài)代理

5.1.1 創(chuàng)建接口

packagestaticProxyPattern;// 創(chuàng)建法院接口publicinterfaceCourt{voiddoCourt();}

5.1.2 實(shí)現(xiàn)接口

packagestaticProxyPattern;publicclassPeopleimplementsCourt{//實(shí)現(xiàn)Court接口//在法庭上張三自己進(jìn)行辯解@OverridepublicvoiddoCourt(){System.out.println("張三說自己沒有偷東西");}}

5.1.3 對(duì)實(shí)現(xiàn)類添加功能

packagestaticProxyPattern;publicclassLawyerimplementsCourt{//接收需要代理的對(duì)象Courtzhangsan;publicLawyer(Courtzhangsan){this.zhangsan=zhangsan;}publicLawyer(){}//張三請(qǐng)律師進(jìn)行辯解@OverridepublicvoiddoCourt(){//張三自己先辯解zhangsan.doCourt();//律師替張三辯解System.out.println("經(jīng)視頻證明,并不是當(dāng)事人偷得東西");}}

5.1.4 測(cè)試

packagestaticProxyPattern;publicclassTest{publicstaticvoidmain(String[]args){//張三請(qǐng)律師打官司Peoplezhangsan=newPeople();Lawyerlawyer=newLawyer(zhangsan);lawyer.doCourt();}}

5.1.5 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):可以做到在符合開閉原則的情況下對(duì)目標(biāo)對(duì)象進(jìn)行功能擴(kuò)展。

缺點(diǎn):我們得為每一個(gè)服務(wù)都得創(chuàng)建代理類,工作量太大,不易管理;同時(shí)接口一旦發(fā)生改變,代理類也得相應(yīng)修改。

如何解決靜態(tài)代理的缺點(diǎn)呢? 這里就得說說動(dòng)態(tài)代理了。

在動(dòng)態(tài)代理中我們不再需要再手動(dòng)的創(chuàng)建代理類,我們只需要編寫一個(gè)動(dòng)態(tài)處理器就可以了。真正的代理對(duì)象由JDK再運(yùn)行時(shí)為我們動(dòng)態(tài)的來創(chuàng)建。

5.2 JDK中生成代理對(duì)象的API

代理類所在包:java.lang.reflect.Proxy;

JDK實(shí)現(xiàn)代理只需要使用newProxyInstance方法,但是該方法需要接收三個(gè)參數(shù),完整的寫法是:

staticObjectnewProxyInstance(ClassLoaderloader,Class<?>[]interfaces,InvocationHandlerh)

返回值:Object就是代理對(duì)象

ClassLoaderloader//代表與目標(biāo)對(duì)象相同的類加載器-------目標(biāo)對(duì)象.getClass().getClassLoader()Class<?>[]interfaces//代表與目標(biāo)對(duì)象實(shí)現(xiàn)的所有的接口字節(jié)碼對(duì)象數(shù)組----數(shù)組因?yàn)槟繕?biāo)類可以有多個(gè)接口InvocationHandlerh//事件處理,執(zhí)行目標(biāo)對(duì)象的方法時(shí),會(huì)觸發(fā)事件處理器的方法,//會(huì)把當(dāng)前執(zhí)行目標(biāo)對(duì)象的方法作為參數(shù)傳入。

5.3 動(dòng)態(tài)代理代碼實(shí)現(xiàn)

5.3.1 創(chuàng)建接口

packagestaticProxyPattern;// 創(chuàng)建法院接口publicinterfaceCourt{voiddoCourt();}

5.3.2 實(shí)現(xiàn)接口

packagestaticProxyPattern;publicclassPeopleimplementsCourt{//實(shí)現(xiàn)Court接口//在法庭上張三自己進(jìn)行辯解@OverridepublicvoiddoCourt(){System.out.println("張三說自己沒有偷東西");}}

5.3.3 代理律師

packagestaticProxyPattern;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;publicclassLawyer{publicObjectgetLawyer(Courtzhangsan){returnProxy.newProxyInstance(//對(duì)象的類加載器zhangsan.getClass().getClassLoader(),//該對(duì)象實(shí)現(xiàn)的所有的接口newClass[]{Court.class},//對(duì)該對(duì)象添加功能newInvocationHandler(){//proxy就是目標(biāo)對(duì)象,method就是調(diào)用目標(biāo)對(duì)象中方法,args就是調(diào)用目標(biāo)對(duì)象中方法的參數(shù)。//proxy的作用://1.可以使用反射獲取代理對(duì)象的信息(也就是proxy.getClass().getName())。//2.可以將代理對(duì)象返回以進(jìn)行連續(xù)調(diào)用,這就是proxy存在的目的,因?yàn)閠his并不是代理對(duì)象。@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{//律師進(jìn)行申辯System.out.println("經(jīng)視頻證明,并不是當(dāng)事人偷得東西");//張三自己進(jìn)行申辯Objectinvoke=method.invoke(zhangsan,args);System.out.println("法院宣布,張三無罪釋放");returninvoke;}});}}

5.3.4 測(cè)試代碼

packagestaticProxyPattern;publicclassTest{publicstaticvoidmain(String[]args){//張三請(qǐng)律師打官司Peoplezhangsan=newPeople();Courtlawyer=(Court)newLawyer().getLawyer(zhangsan);lawyer.doCourt();}}

5.3.5 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

相對(duì)于靜態(tài)代理,動(dòng)態(tài)代理大大減少了我們的開發(fā)任務(wù),同時(shí)減少了對(duì)業(yè)務(wù)接口的依賴,降低了耦合度。

缺點(diǎn):

代理對(duì)象不需要實(shí)現(xiàn)接口,但是目標(biāo)對(duì)象一定要實(shí)現(xiàn)接口,否則不能用動(dòng)態(tài)代理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 定義:為其它對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。使用場(chǎng)景:當(dāng)無法或不想直接訪問某個(gè)對(duì)象或訪問某個(gè)對(duì)象存在困難時(shí)...
    王靈閱讀 472評(píng)論 0 0
  • 我是游戲至尊 2007年,感覺很無聊,于是就玩了一段時(shí)間的網(wǎng)絡(luò)游戲,游戲名就不說了,要不就有做廣告的嫌疑,反正就是...
    WILL_HUNTING閱讀 540評(píng)論 0 0
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,674評(píng)論 1 32
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李頭閱讀 3,397評(píng)論 2 10
  • 白楊師姐是女兒給我介紹的,我一看是滿滿的正能量。于是加到群里,先是看到白楊師姐的日更100篇文章,接著是21天自律...
    王琴wq70閱讀 251評(píng)論 0 1

友情鏈接更多精彩內(nèi)容