Android中的设计模式之代理模式
參考
- 《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ) 》4.7 Proxy 代理--對象結(jié)構(gòu)型模式
- 《Android源碼設(shè)計模式解析與實戰(zhàn)》第18章 編程好幫手--代理模式
意圖
為其它對象提供一種代理以控制對這個對象的訪問
適用性
在需要用比較通用和復(fù)雜的對象指針代替簡單的指針的時候,使用Proxy模式。
- 遠程代理 為一個對象在不同的地址空間提供局部代表。這一點Android Binde實現(xiàn)跨進程通信很典型
- 虛代理 根據(jù)需要創(chuàng)建開銷很大的對象。
- 保護代理 控制對原始對象的訪問。保護代理用于對象應(yīng)該有不同的訪問權(quán)限的時候。
- 智能指引 取代了簡單的指針,它在訪問對象時執(zhí)行一些附加操作。
- 對指向?qū)嶋H對象的引用計數(shù),這樣當(dāng)該對象沒有引用時,可以自動釋放它,難道Java就是這個原理?
- 當(dāng)?shù)谝淮我靡粋€持久對象時,將它裝入內(nèi)存
- 在訪問一個實際對象前,檢查是否已經(jīng)鎖定了它,以確保其它對象不能改變它。
結(jié)構(gòu)
代理模式結(jié)構(gòu)角色
- Client
客戶類,即使用代理類的類型
- Subject 抽象主題類 抽象了代理行為
主要職責(zé)是聲明真實主題與代理的共同接口關(guān)系,該類既可以是一個抽象類也可以是一個接口。
- RealSubject 實現(xiàn)抽象主題的真實主題類
被委托類或被代理類,定義了代理所表示的真實對象,由其執(zhí)行具體的業(yè)務(wù)邏輯方法,而客戶端則通過代理類間接地調(diào)用真實主題類中定義的方法。
- Proxy 委托類或代理類
- 持有對真實主題類的引用,可以訪問真實實體
- 提供一個與Subject的接口相同的接口,這樣代理就可以用來替代實體
- 控制對實體的存取,并可能負責(zé)創(chuàng)建或者刪除它
- 相對與實體的其它附加功能依賴于代理的類型
協(xié)作
代理根據(jù)其種類,在適當(dāng)?shù)臅r候向RealSubject轉(zhuǎn)發(fā)請求
代理執(zhí)行流程效果
Proxy模式在訪問對象時引入了一定程度的間接性。根據(jù)代理的類型,附件的間接性有多種用途
- Remote Proxy可以隱藏一個對象存在不同地址空間的事實。
- Virtual Proxy 可以進行優(yōu)化,例如根據(jù)要求創(chuàng)建對象。
- Protection Proxies和Smart Reference都允許在訪問一個對象時有一些附加的內(nèi)務(wù)處理
應(yīng)用例子1 小明打官司
描述
小明被老板拖欠工資,小明選擇了走發(fā)法律途徑解決該糾紛。所以小明請律師作為自己的訴訟代理人。
結(jié)構(gòu)
結(jié)構(gòu)java實現(xiàn)
/** * * @author newtrekwang * @desc 代理接口 * 2017年3月4日 */ public interface ILawSuit { // 提交申請void submit(); // 進行舉證void burden(); // 開始辯護void defend(); // 訴訟完成void finish(); }/** * * @author newtrekwang * @desc 被代理者小明 * 2017年3月4日 */ public class XiaoMin implements ILawSuit{@Overridepublic void submit() {//小明申請仲裁System.out.println("老板拖欠工資,特此申請仲裁!");}@Overridepublic void burden() {System.out.println("這是合同書和過去一年的銀行工資流水");}@Overridepublic void defend() {System.out.println("證據(jù)確鑿,不需要再說什么了");}@Overridepublic void finish() {System.out.println("訴訟成功!判決老板即日起七天內(nèi)結(jié)算工資!");}}/** * * @author newtrekwang * @desc 代理律師 * 2017年3月4日 */ public class Lawyer implements ILawSuit { // 持有一個具體被代理者的引用private ILawSuit mLawSuit;public Lawyer(ILawSuit iLawSuit) {this.mLawSuit=iLawSuit;}@Overridepublic void submit() {mLawSuit.submit();}@Overridepublic void burden() {mLawSuit.burden();}@Overridepublic void defend() {mLawSuit.defend();}@Overridepublic void finish() {mLawSuit.finish();}}客戶使用
public static void main(String[] args) {ILawSuit xiaoMin=new XiaoMin();Lawyer lawyer=new Lawyer(xiaoMin);lawyer.submit();lawyer.burden();lawyer.defend();lawyer.finish();}結(jié)果
老板拖欠工資,特此申請仲裁! 這是合同書和過去一年的銀行工資流水 證據(jù)確鑿,不需要再說什么了 訴訟成功!判決老板即日起七天內(nèi)結(jié)算工資!java的靜態(tài)代理和動態(tài)代理
- 靜態(tài)代理:靜態(tài)代理如上述代碼一樣,代理者的代碼由程序員自己或通過一些自動化工具生成固定的代碼再對其進行編譯,也就是說我們的代碼運行前代理類的class編譯文件就已存在;
- 動態(tài)代理:與靜態(tài)代理相反,通過反射機制動態(tài)地生成代理者的對象,也就是說我們在code階段不知道要代理誰,代理誰我們將會在執(zhí)行階段決定。而Java也給我們提供了一個便捷的動態(tài)代理接口InvocationHandler,實現(xiàn)該接口需要重寫其調(diào)用方法invoke.
使用
public static void main(String[] args) { // 構(gòu)造一個小明ILawSuit xiaoMin=new XiaoMin(); // 構(gòu)造一個動態(tài)代理DynamicProxy dynamicProxy=new DynamicProxy(xiaoMin); // 獲取被代理類小明的ClassLoaderClassLoader loader=xiaoMin.getClass().getClassLoader(); // 動態(tài)構(gòu)造一個代理者律師ILawSuit lawyer=(ILawSuit) Proxy.newProxyInstance(loader, new Class[]{ILawSuit.class}, dynamicProxy);lawyer.submit();lawyer.burden();lawyer.defend();lawyer.finish();}結(jié)果
老板拖欠工資,特此申請仲裁! 這是合同書和過去一年的銀行工資流水 證據(jù)確鑿,不需要再說什么了 訴訟成功!判決老板即日起七天內(nèi)結(jié)算工資!應(yīng)用例子2 嵌入圖形對象的文檔編輯器
描述
對一個對象進行訪問控制的一個原因時為了只有在我們真正需要這個對象時才對它進行創(chuàng)建和初始化。考慮一個可以在文檔中嵌入圖形對象的文檔編輯器,有些圖形對象(大圖)的創(chuàng)建開銷很大,但是打開文檔必須很迅速,因此我們在打開文檔時應(yīng)避免一次性創(chuàng)建所有開銷很大的對象,因為并非所有這些對象在文檔中都同時可見,所以也沒有必要同時創(chuàng)建這些對象。
這一限制條件意味著,對于每一個開銷很大的對象,應(yīng)該根據(jù)需要進行創(chuàng)建。問題的解決方案就是使用另一個對象,即圖像Proxy,代替那個真正的圖像。Proxy可以代替一個圖像對象,并且在需要時負責(zé)實例化這個圖像對象。
結(jié)構(gòu)
結(jié)構(gòu)源碼就略了
應(yīng)用例子3 Retrofit 中的動態(tài)代理
待更
應(yīng)用例子4 Android Service代理
待更
總結(jié)
以上是生活随笔為你收集整理的Android中的设计模式之代理模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx: [error] open(
- 下一篇: HTML5调用手机前置摄像头或后置摄像头