摘要:代理模式代理類中創建一個真實對象的實例模式的核心裝飾者強調的是增強自身,在被裝飾之后你能夠在被增強的類上使用增強后的功能。
代理模式
在詳細了解代理模式之前,可能對于像小秋一樣的小白,只知道一些很淺顯的概念,或者就知道遠程代理啊,靜態代理啊,動態代理啊,這些看似可以望文生義的專業名詞,但是如果我告訴你代理模式貫穿了我們生活的方方面面,就比如你現在刷著公眾號的時候,實際上就用了遠程代理模式你信嗎,當你打開一個很大的網頁,你能很快的打開,但是你有沒有發現,當你往下滑的時候,圖片才開始一張一張的展現出來,這個背后實際上也是用了代理模式,具體是咋回事,和小秋一起看下去吧~
概念為其他類提供一種代理,以控制對這個類的訪問
動機在直接訪問對象時帶來的問題,比如說:要訪問的對象在遠程的機器上。在面向對象系統中,有些對象由于某些原因(比如對象創建開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問),直接訪問會給使用者或者系統結構帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。
結構 組件抽象角色
通過接口或抽象類聲明真實角色實現的業務方法。
代理角色
實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,并可以附加自己的操作
真實角色
實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色調用
分類 靜態代理靜態代理在使用時,需要定義接口或者父類,被代理對象與代理對象一起實現相同的接口或者是繼承相同父類
實現這里引用《大話設計模式》里面的一個例子說明:追求者找同學送禮物給女神
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(); }
真實角色
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(); } }動態代理
代理對象,不需要實現接口,但需要指定接口的類型
代理對象的生成,是利用JDK的API,動態的在內存中構建代理對象(需要我們指定創建代理對象/目標對象實現的接口的類型)
動態代理也叫做:JDK代理,接口代理
下面我們用動態代理的方式實現上面送禮物的過程
首先先創建抽象委托類
package dynamic; //委托抽象類 public interface SendGift { public boolean sendFlower(); public boolean sendCake(); }
然后創建具體委托類
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; //真實委托類 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; } }
創建中間類實現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()生成的代理類對象 * @param method 表示代理對象被調用的函數 * @param args 表示代理類對象被調用的函數的參數 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始送禮物"); //target 屬性表示真實委托類對象。 Object obj = method.invoke(target, args); System.out.println("送禮物完成"); return obj; } }
客戶端通過proxy類新建代理對象
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(); } } // 開始送禮物 // 小王送芳芳蛋糕 // 送禮物完成 // 始送禮物 // 小王送芳芳花 // 送禮物完成應用場景 遠程代理 概念
為一個位于不同地址空間的遠程對象提供一個局域代表對象,這個不同的地址空間可以位于同一臺機器中,也可以位于不同的機器中
應用場景Java使用RMI實現遠程代理、web service
虛擬代理 概念根據需要創建開銷很大的對象。通過代理對象來存放實例化需要很長時間的真實對象
優點性能優化,減少響應時間
節省內存,推遲對象的實例化時間
加速應用程序的啟動
缺點不能保證特定的應用程序被創建,每次訪問這個對象的時候都需要判斷是否為null,增加了檢測時間
流程代理對象和真實對象實現相同的接口
代理對象把真實對象的引用作為它的實例變量的維護
當客戶需要真實對象的時候,代理對象首先會檢測真實對象是否已經被創建
如果沒有,由代理對象創建真實對象,并把這個對象分配給引用變量,代理對象把調用轉發給真實對象
應用場景打開一個很大的HTML網頁,可以很快的打開,但是圖片卻是隨著用戶的滑動一張一張的加載,這時虛擬代理代替了真實的圖片,存儲了真實圖片的路徑和尺寸
安全代理控制對一個對象的訪問權限。
與裝飾者模式的區別 相同點UML類圖基本沒區別,都是實現同一個接口,一個類包裝另一 個類。
兩者都是對類的方法進行擴展
代理模式的結構圖
裝飾者模式的結構圖
不同點對對象的作用
裝飾者:動態的新增或組合對象的行為,在不改變接口的前提下,動態擴展對象的功能
代理模式:為其他對象提供一種代理以控制對這個對象的訪問,在不改變接口的前提下,控制對象的訪問
如何使用該對象
裝飾者:通常將原始對象作為參數傳遞給Decorator的構造函數。
代理模式:代理類中創建一個真實對象的實例
模式的核心
裝飾者:強調的是增強自身,在被裝飾之后你能夠在被增強的類上使用增強后的功能。增強后你還是你,只不過能力更強了而已
代理模式:強調要讓別人去做一些本身和你業務沒有太多關系的職責(記錄日志,設置緩存,遠程代理負責網絡通信的一些細節),代理模式是為了實現對對象的控制,因為被代理的對象往往難以直接獲得或者其內部不想暴露出來
最后貼上一張概覽圖,復習一下~現在是不是覺得豁然開朗
參考
菜鳥教程
Java的三種代理模式
設計模式之---代理模式(AOP的原理)
[[Java的三種代理模式]](https://segmentfault.com/a/11...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74898.html
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:以下知識點是前輩師兄總結基礎語義化標簽引進了一些新的標簽,特別注意等,注意的標題結構理解瀏覽器解析的過程,理解的樹形結構,及相應理解標簽在各個瀏覽器上的默認樣式代理樣式,理解中的重置樣式表的概念理解等功能性標簽理解標簽,理解文件提交過程推薦 以下知識點是前輩師兄總結 1、HTML/HTML5基礎: 1.0、語義化H5標簽1.1、H5引進了一些新的標簽,特別注意article...
摘要:以下知識點是前輩師兄總結基礎語義化標簽引進了一些新的標簽,特別注意等,注意的標題結構理解瀏覽器解析的過程,理解的樹形結構,及相應理解標簽在各個瀏覽器上的默認樣式代理樣式,理解中的重置樣式表的概念理解等功能性標簽理解標簽,理解文件提交過程推薦 以下知識點是前輩師兄總結 1、HTML/HTML5基礎: 1.0、語義化H5標簽1.1、H5引進了一些新的標簽,特別注意article...
閱讀 2298·2021-11-15 11:37
閱讀 2974·2021-09-01 10:41
閱讀 801·2019-12-27 11:58
閱讀 756·2019-08-30 15:54
閱讀 724·2019-08-30 13:52
閱讀 2938·2019-08-29 12:22
閱讀 1083·2019-08-28 18:27
閱讀 1464·2019-08-26 18:42