摘要:代理模式代理類中創(chuàng)建一個(gè)真實(shí)對(duì)象的實(shí)例模式的核心裝飾者強(qiáng)調(diào)的是增強(qiáng)自身,在被裝飾之后你能夠在被增強(qiáng)的類上使用增強(qiáng)后的功能。
代理模式
在詳細(xì)了解代理模式之前,可能對(duì)于像小秋一樣的小白,只知道一些很淺顯的概念,或者就知道遠(yuǎn)程代理啊,靜態(tài)代理啊,動(dòng)態(tài)代理啊,這些看似可以望文生義的專業(yè)名詞,但是如果我告訴你代理模式貫穿了我們生活的方方面面,就比如你現(xiàn)在刷著公眾號(hào)的時(shí)候,實(shí)際上就用了遠(yuǎn)程代理模式你信嗎,當(dāng)你打開一個(gè)很大的網(wǎng)頁,你能很快的打開,但是你有沒有發(fā)現(xiàn),當(dāng)你往下滑的時(shí)候,圖片才開始一張一張的展現(xiàn)出來,這個(gè)背后實(shí)際上也是用了代理模式,具體是咋回事,和小秋一起看下去吧~
概念為其他類提供一種代理,以控制對(duì)這個(gè)類的訪問
動(dòng)機(jī)在直接訪問對(duì)象時(shí)帶來的問題,比如說:要訪問的對(duì)象在遠(yuǎn)程的機(jī)器上。在面向?qū)ο笙到y(tǒng)中,有些對(duì)象由于某些原因(比如對(duì)象創(chuàng)建開銷很大,或者某些操作需要安全控制,或者需要進(jìn)程外的訪問),直接訪問會(huì)給使用者或者系統(tǒng)結(jié)構(gòu)帶來很多麻煩,我們可以在訪問此對(duì)象時(shí)加上一個(gè)對(duì)此對(duì)象的訪問層。
結(jié)構(gòu) 組件抽象角色
通過接口或抽象類聲明真實(shí)角色實(shí)現(xiàn)的業(yè)務(wù)方法。
代理角色
實(shí)現(xiàn)抽象角色,是真實(shí)角色的代理,通過真實(shí)角色的業(yè)務(wù)邏輯方法來實(shí)現(xiàn)抽象方法,并可以附加自己的操作
真實(shí)角色
實(shí)現(xiàn)抽象角色,定義真實(shí)角色所要實(shí)現(xiàn)的業(yè)務(wù)邏輯,供代理角色調(diào)用
分類 靜態(tài)代理靜態(tài)代理在使用時(shí),需要定義接口或者父類,被代理對(duì)象與代理對(duì)象一起實(shí)現(xiàn)相同的接口或者是繼承相同父類
實(shí)現(xiàn)這里引用《大話設(shè)計(jì)模式》里面的一個(gè)例子說明:追求者找同學(xué)送禮物給女神
package proxy; public class Girl { private String name; private int age; public Girl(String name) { this.name = name; } public String getName() { return name; } }
抽象角色
package proxy; public interface SendGift { public void sendFlower(); public void sendCake(); }
真實(shí)角色
package proxy; public class Persuit implements SendGift { private Girl girl; public Persuit(Girl girl) { this.girl = girl; } @Override public void sendFlower() { System.out.println(girl.getName() + "送你花"); } @Override public void sendCake() { System.out.println(girl.getName() + "送你蛋糕"); } }
代理角色
package proxy; public class Proxy implements SendGift { private Persuit persuit; public Proxy(Girl girl){ persuit = new Persuit(girl); } @Override public void sendFlower() { persuit.sendFlower(); } @Override public void sendCake() { persuit.sendCake(); } }動(dòng)態(tài)代理
代理對(duì)象,不需要實(shí)現(xiàn)接口,但需要指定接口的類型
代理對(duì)象的生成,是利用JDK的API,動(dòng)態(tài)的在內(nèi)存中構(gòu)建代理對(duì)象(需要我們指定創(chuàng)建代理對(duì)象/目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類型)
動(dòng)態(tài)代理也叫做:JDK代理,接口代理
下面我們用動(dòng)態(tài)代理的方式實(shí)現(xiàn)上面送禮物的過程
首先先創(chuàng)建抽象委托類
package dynamic; //委托抽象類 public interface SendGift { public boolean sendFlower(); public boolean sendCake(); }
然后創(chuàng)建具體委托類
package dynamic; public class Girl { private String name; private int age; public Girl(String name) { this.name = name; } public String getName() { return name; } }
package dynamic; import static java.lang.Thread.sleep; //真實(shí)委托類 public class Persuit implements SendGift { private Girl girl; private String name; public Persuit(Girl girl, String name) { this.girl = girl; this.name = name; } public String getName() { return name; } @Override public boolean sendFlower() { System.out.println( name +"送"+girl.getName()+"花"); return true; } @Override public boolean sendCake() { System.out.println( name +"送"+girl.getName()+"蛋糕"); return true; } }
創(chuàng)建中間類實(shí)現(xiàn)InvocationHandler接口
package dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class TimingInvocationHandler implements InvocationHandler { private Object target; // private Persuit target;這里的成員變量類型可以換成object類型 public TimingInvocationHandler(Object target) { super(); this.target = target; } public TimingInvocationHandler() { super(); } /** * * @param proxy 通過Proxy.newProxyInstance()生成的代理類對(duì)象 * @param method 表示代理對(duì)象被調(diào)用的函數(shù) * @param args 表示代理類對(duì)象被調(diào)用的函數(shù)的參數(shù) * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始送禮物"); //target 屬性表示真實(shí)委托類對(duì)象。 Object obj = method.invoke(target, args); System.out.println("送禮物完成"); return obj; } }
客戶端通過proxy類新建代理對(duì)象
package dynamic; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) throws InterruptedException { Girl girl = new Girl("芳芳"); TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new Persuit(girl,"小王")); SendGift sendGift = (SendGift) Proxy.newProxyInstance(SendGift.class.getClassLoader(), new Class[]{SendGift.class}, timingInvocationHandler); // call method of proxy instance sendGift.sendCake(); sendGift.sendFlower(); } } // 開始送禮物 // 小王送芳芳蛋糕 // 送禮物完成 // 始送禮物 // 小王送芳芳花 // 送禮物完成應(yīng)用場(chǎng)景 遠(yuǎn)程代理 概念
為一個(gè)位于不同地址空間的遠(yuǎn)程對(duì)象提供一個(gè)局域代表對(duì)象,這個(gè)不同的地址空間可以位于同一臺(tái)機(jī)器中,也可以位于不同的機(jī)器中
應(yīng)用場(chǎng)景Java使用RMI實(shí)現(xiàn)遠(yuǎn)程代理、web service
虛擬代理 概念根據(jù)需要?jiǎng)?chuàng)建開銷很大的對(duì)象。通過代理對(duì)象來存放實(shí)例化需要很長(zhǎng)時(shí)間的真實(shí)對(duì)象
優(yōu)點(diǎn)性能優(yōu)化,減少響應(yīng)時(shí)間
節(jié)省內(nèi)存,推遲對(duì)象的實(shí)例化時(shí)間
加速應(yīng)用程序的啟動(dòng)
缺點(diǎn)不能保證特定的應(yīng)用程序被創(chuàng)建,每次訪問這個(gè)對(duì)象的時(shí)候都需要判斷是否為null,增加了檢測(cè)時(shí)間
流程代理對(duì)象和真實(shí)對(duì)象實(shí)現(xiàn)相同的接口
代理對(duì)象把真實(shí)對(duì)象的引用作為它的實(shí)例變量的維護(hù)
當(dāng)客戶需要真實(shí)對(duì)象的時(shí)候,代理對(duì)象首先會(huì)檢測(cè)真實(shí)對(duì)象是否已經(jīng)被創(chuàng)建
如果沒有,由代理對(duì)象創(chuàng)建真實(shí)對(duì)象,并把這個(gè)對(duì)象分配給引用變量,代理對(duì)象把調(diào)用轉(zhuǎn)發(fā)給真實(shí)對(duì)象
應(yīng)用場(chǎng)景打開一個(gè)很大的HTML網(wǎng)頁,可以很快的打開,但是圖片卻是隨著用戶的滑動(dòng)一張一張的加載,這時(shí)虛擬代理代替了真實(shí)的圖片,存儲(chǔ)了真實(shí)圖片的路徑和尺寸
安全代理控制對(duì)一個(gè)對(duì)象的訪問權(quán)限。
與裝飾者模式的區(qū)別 相同點(diǎn)UML類圖基本沒區(qū)別,都是實(shí)現(xiàn)同一個(gè)接口,一個(gè)類包裝另一 個(gè)類。
兩者都是對(duì)類的方法進(jìn)行擴(kuò)展
代理模式的結(jié)構(gòu)圖
裝飾者模式的結(jié)構(gòu)圖
不同點(diǎn)對(duì)對(duì)象的作用
裝飾者:動(dòng)態(tài)的新增或組合對(duì)象的行為,在不改變接口的前提下,動(dòng)態(tài)擴(kuò)展對(duì)象的功能
代理模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問,在不改變接口的前提下,控制對(duì)象的訪問
如何使用該對(duì)象
裝飾者:通常將原始對(duì)象作為參數(shù)傳遞給Decorator的構(gòu)造函數(shù)。
代理模式:代理類中創(chuàng)建一個(gè)真實(shí)對(duì)象的實(shí)例
模式的核心
裝飾者:強(qiáng)調(diào)的是增強(qiáng)自身,在被裝飾之后你能夠在被增強(qiáng)的類上使用增強(qiáng)后的功能。增強(qiáng)后你還是你,只不過能力更強(qiáng)了而已
代理模式:強(qiáng)調(diào)要讓別人去做一些本身和你業(yè)務(wù)沒有太多關(guān)系的職責(zé)(記錄日志,設(shè)置緩存,遠(yuǎn)程代理負(fù)責(zé)網(wǎng)絡(luò)通信的一些細(xì)節(jié)),代理模式是為了實(shí)現(xiàn)對(duì)對(duì)象的控制,因?yàn)楸淮淼膶?duì)象往往難以直接獲得或者其內(nèi)部不想暴露出來
最后貼上一張概覽圖,復(fù)習(xí)一下~現(xiàn)在是不是覺得豁然開朗
參考
菜鳥教程
Java的三種代理模式
設(shè)計(jì)模式之---代理模式(AOP的原理)
[[Java的三種代理模式]](https://segmentfault.com/a/11...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/74898.html
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...
摘要:中的詳解必修個(gè)多線程問題總結(jié)個(gè)多線程問題總結(jié)有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升開源的運(yùn)行原理從虛擬機(jī)工作流程看運(yùn)行原理。 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 基于 POI 封裝 ExcelUtil 精簡(jiǎn)的 Excel 導(dǎo)入導(dǎo)出 由于 poi 本身只是針對(duì)于 ...
摘要:以下知識(shí)點(diǎn)是前輩師兄總結(jié)基礎(chǔ)語義化標(biāo)簽引進(jìn)了一些新的標(biāo)簽,特別注意等,注意的標(biāo)題結(jié)構(gòu)理解瀏覽器解析的過程,理解的樹形結(jié)構(gòu),及相應(yīng)理解標(biāo)簽在各個(gè)瀏覽器上的默認(rèn)樣式代理樣式,理解中的重置樣式表的概念理解等功能性標(biāo)簽理解標(biāo)簽,理解文件提交過程推薦 以下知識(shí)點(diǎn)是前輩師兄總結(jié) 1、HTML/HTML5基礎(chǔ): 1.0、語義化H5標(biāo)簽1.1、H5引進(jìn)了一些新的標(biāo)簽,特別注意article...
摘要:以下知識(shí)點(diǎn)是前輩師兄總結(jié)基礎(chǔ)語義化標(biāo)簽引進(jìn)了一些新的標(biāo)簽,特別注意等,注意的標(biāo)題結(jié)構(gòu)理解瀏覽器解析的過程,理解的樹形結(jié)構(gòu),及相應(yīng)理解標(biāo)簽在各個(gè)瀏覽器上的默認(rèn)樣式代理樣式,理解中的重置樣式表的概念理解等功能性標(biāo)簽理解標(biāo)簽,理解文件提交過程推薦 以下知識(shí)點(diǎn)是前輩師兄總結(jié) 1、HTML/HTML5基礎(chǔ): 1.0、語義化H5標(biāo)簽1.1、H5引進(jìn)了一些新的標(biāo)簽,特別注意article...
閱讀 2285·2021-11-15 11:37
閱讀 2954·2021-09-01 10:41
閱讀 787·2019-12-27 11:58
閱讀 747·2019-08-30 15:54
閱讀 715·2019-08-30 13:52
閱讀 2930·2019-08-29 12:22
閱讀 1075·2019-08-28 18:27
閱讀 1452·2019-08-26 18:42