代理模式(為了Rxjava,Retrofit....)

以下都是本人收集和總結(jié)的內(nèi)容:

1.什么是代理模式

代理模式(Proxy Pattern)也稱作為委托模式蚕断。在生活中代理也是隨處可見欢伏,例如香港代購,代理品牌電腦出售店等亿乳。而在開發(fā)中也是被經(jīng)常被使用到的一種設計模式硝拧。代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。對于代理模式可以分為兩大類葛假,分別是靜態(tài)代理和動態(tài)代理障陶。下面就開始對這兩種類型的代理模式進行詳細介紹。

2. 什么是靜態(tài)代理

在這里通過一個場景來展開描述代理模式⊥┛睿現(xiàn)在我想按照自己想要的配置來組裝一臺電腦咸这。于是我將主板,內(nèi)存條魔眨,顯卡媳维,機箱酿雪,顯示器等所有的配件都買回來了≈豆簦可是這個時候遇到了一個難題指黎,我不會組裝呀。于是我?guī)е@些配件去找專業(yè)人士為我組裝電腦州丹。對于電腦的組裝內(nèi)部細節(jié)部分步驟比較多醋安。在這里作為舉例說明,將組裝電腦的過程主要分為三個步驟墓毒。這三個步驟分別是安裝主機吓揪,設置顯示器,安裝操作系統(tǒng)所计。

2.1 靜態(tài)代理簡單實現(xiàn)

接下來我們針對上述場景柠辞,來實現(xiàn)代理模式。首先來看一下它的UML類圖主胧。

代理uml

從上述大概看出代理模式創(chuàng)建很簡單叭首。在這里定義了一個電腦公司的接口。在這個接口里面是一些出售電腦并且組裝的實現(xiàn)步驟踪栋。而后又定義了一個客戶類和一個銷售的代理類焙格,分別實現(xiàn)這個接口。之后出售電腦的這些事情全部都交由這個銷售代理類來實現(xiàn)夷都。下面就來看一下具體的代碼實現(xiàn)眷唉。
  這里定義一個電腦公司的接口,在接口里面分別定義了對電腦的出售,主機的安裝和操作系統(tǒng)的安裝损肛。

public interface IComputerFirmbuild {
    void saleComputer();
    void installHost();
    void installOS();
}

下面這個是客戶類厢破,實現(xiàn)了IComputerFirmbuild接口。也是對電腦服務的具體操作步驟治拿。

public class Customer implements IComputerFirmbuild{

    @Override
    public void saleComputer() {
        System.out.println("購買電腦");
    }

    @Override
    public void installHost() {
        System.out.println("安裝主機");
    }

    @Override
    public void installOS() {
        System.out.println("安裝操作系統(tǒng)");
    }

}

還有個代理類摩泪。這個代理類同樣也繼承自IComputerFirmbuild接口。在這個代理類中還持有被代理的引用劫谅,也就是Customer類见坑。通過調(diào)用被代理類Customer的方法,來實現(xiàn)代理功能捏检。

public class SalerProxy implements IComputerFirmbuild{

    private IComputerFirmbuild saler;

    public SalerProxy(IComputerFirmbuild saler) {
        this.saler = saler;
    }
     
    @Override
    public void saleComputer() {
        this.Saler.saleComputer();
    }
    
    @Override
    public void installHost() {
        this.Saler.installHost();
    }

    @Override
    public void installOS() {
        this.saler.installOS();
    }

}

下面就通過一個Client類荞驴,來看一下具體的調(diào)用執(zhí)行關系。

public class Client {

    public static void main(String[] args) {
        IComputerFirmbuild customer = new Customer();
        IComputerFirmbuild proxy = new SalerProxy(customer);
        proxy.saleComputer();
        proxy.setDisplay();
        proxy.installOS();
    }

}

在這個Client類中贯城,可以看到熊楼,所有的事情都交由代理類處理了。然后在看一下運行結(jié)果能犯。

log -->  購買電腦
log -->  安裝主機
log -->  安裝操作系統(tǒng)

對于這個代理類中鲫骗,也能夠?qū)崿F(xiàn)不同的接口來完成不同功能的整合犬耻。在這里就不在詳細贅述。下面就來看一下代理模式的通用代碼执泰。

2.2靜態(tài)代理通用模板

在這里首先來看一下代理模式的通用類圖枕磁。

代理模式的通用類圖.jpeg

ISubject(抽象主題類):在這個類中,主要聲明真實主題類和代理類的共同方法术吝。它既可以是一個接口也可以是一個抽象類计济。
  RealSubject(真實主題類):這是被代理類,具體的業(yè)務實現(xiàn)都在這個類中排苍。
  Proxy(代理類):這是一個代理類沦寂,在這個代理類中它持有真實主題類的對象。通過調(diào)用真實主題類的方法來實現(xiàn)代理淘衙。
  下面來看一下通用代碼:
  抽象主題類

public interface ISubject {
   public void request();
}

實現(xiàn)抽象主題的真實主題類

public class RealSubject implements ISubject{

    @Override
    public void request() {
        System.out.println("我是真實對象");
    }
}

代理類

public class Proxy implements ISubject{

    private ISubject subject;

    public Proxy(ISubject subject) {
        this.subject = subject;
    }

    @Override
    public void request() {
        this.subject.request();
    }

}

客戶類

public class Client {
    public static void main(String[] args) {
        ISubject subject = new RealSubject();
        Proxy proxy = new Proxy(subject);
        proxy.request();
    }
}

以上就是靜態(tài)代理類的實現(xiàn)凑队。
  從上面的分析出可以看出,對靜態(tài)代理模式幔翰,代理者的代碼都是通過程序員或者是通過一些自動化的工具生成的固定代碼然后再對他們進行編譯。這樣也就意味著在我們的代碼運行之前代理類的Class文件就已經(jīng)存在了西壮。

3. 什么是動態(tài)代理

3.1動態(tài)代理簡單實現(xiàn)

在這里再來看一下動態(tài)代理遗增。對于動態(tài)代理,在程序運行時款青,動態(tài)的創(chuàng)建一個代理類以及代理類的對象做修,當然也能夠創(chuàng)建一個實現(xiàn)多個接口的代理類。在動態(tài)代理類中使用了Java中的反射機制抡草,來生成了代理類的對象饰及。并且Java也為我們提供了一個動態(tài)代理接口InvocationHandler,對被代理類的方法進行代理康震。在使用動態(tài)代理類時燎含,必須實現(xiàn)InvocationHandler接口。
  對于InvocationHandler接口腿短,我們必須手動實現(xiàn)的它的invoke方法屏箍,正是在InvocationHandler中的invoke方法中完成了對真實方法的調(diào)用。也就是說所有被代理的方法都是交由這個InvocationHandler進行處理橘忱。在這里首先看一下這個InvocationHandler接口赴魁。

動態(tài)代理.png

下面就來看一下具體的代碼實現(xiàn)。對于上面的IComputerFirmbuild接口和Customer不需要改變钝诚。所以在這里只需要一個實現(xiàn)InvocationHandler接口的CustomerHandler類颖御。然后在對Client做一次修改即可。在這里看一下CustomerHandler類凝颇。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CustomerHandler implements InvocationHandler{

    private Object obj = null;

    public CustomerHandler(Object object) {
        this.obj = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        return method.invoke(this.obj, args);
    }

}

再看一下Client類潘拱。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        IComputerFirmbuild computerFirmbuild = new Customer();
        InvocationHandler handler = new CustomerHandler(computerFirmbuild);
        IComputerFirmbuild proxy = (IComputerFirmbuild)Proxy.newProxyInstance(computerFirmbuild.getClass().getClassLoader(), 
                new Class[]{IComputerFirmbuild.class}, handler);
        proxy.saleComputer();
        proxy.installHost();
        proxy.installOS();
    }

}

這樣就通過動態(tài)代理模式實現(xiàn)了上述的情形疹鳄。對于運行結(jié)果與上面一樣,在這里就不在貼出泽铛。下面來看一下動態(tài)代理的通用模板尚辑。

通過DynamicProxy,RealSubject可以在運行時動態(tài)改變盔腔,需要控制的接口Subject也可以在運行時改變杠茬,控制的方式DynamicSubject類也可以動態(tài)改變,從而實現(xiàn)了非常靈活的動態(tài)代理關系弛随。

3.2動態(tài)代理通用模板

在這里再看一下動態(tài)代理的通用類圖瓢喉。

動態(tài)代理的通用類圖.jpeg

在這里通過DynamicProxy來創(chuàng)建一個Proxy對象。并且它依賴于InvocationHandler舀透。并且是InvocationHandler來進行實際的業(yè)務處理栓票。下面就來看一下動態(tài)代理的通用代碼。   
抽象主題類

public interface ISubject {
    void request();
}

真實主題類

public class RealSubject implements ISubject{
  @Override
    public void request() {
        //業(yè)務處理
    }

}

InvocationHandler的實現(xiàn)類

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler{
   private Object target = null;
 public MyInvocationHandler(Object object) {
        this.target = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        return method.invoke(this.target, args);
    }

}

DynamicProxy類

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class DynamicProxy<T> {
   @SuppressWarnings("unchecked")
    public static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces,InvocationHandler handler){
        return (T)Proxy.newProxyInstance(classLoader, interfaces, handler);
    }
}

Client類

public class Client {
    public static void main(String[] args) {
        ISubject subject = new RealSubject();

        InvocationHandler handler = new MyInvocationHandler(subject);
        ISubject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
        proxy.request();
    }
}

4. 總結(jié)

從代理模式可以看出代理對象可以在客戶端和目標對象之間起到中介的作用愕够,這樣起到了中介的作用和保護了目標對象的作用走贪,并且擴展性很高。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惑芭,一起剝皮案震驚了整個濱河市坠狡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遂跟,老刑警劉巖逃沿,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異幻锁,居然都是意外死亡凯亮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門哄尔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來假消,“玉大人,你說我怎么就攤上這事究飞≈们” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵亿傅,是天一觀的道長媒峡。 經(jīng)常有香客問我,道長葵擎,這世上最難降的妖魔是什么谅阿? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上签餐,老公的妹妹穿的比我還像新娘寓涨。我一直安慰自己,他們只是感情好氯檐,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布戒良。 她就那樣靜靜地躺著,像睡著了一般冠摄。 火紅的嫁衣襯著肌膚如雪糯崎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天河泳,我揣著相機與錄音沃呢,去河邊找鬼。 笑死拆挥,一個胖子當著我的面吹牛薄霜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纸兔,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惰瓜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了汉矿?” 一聲冷哼從身側(cè)響起鸵熟,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎负甸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痹届,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡呻待,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了队腐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕捉。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柴淘,靈堂內(nèi)的尸體忽然破棺而出迫淹,到底是詐尸還是另有隱情,我是刑警寧澤为严,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布敛熬,位于F島的核電站,受9級特大地震影響第股,放射性物質(zhì)發(fā)生泄漏应民。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诲锹。 院中可真熱鬧繁仁,春花似錦、人聲如沸归园。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庸诱。三九已至捻浦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偶翅,已是汗流浹背默勾。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留聚谁,地道東北人母剥。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像形导,于是被迫代替她去往敵國和親环疼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 整體Retrofit內(nèi)容如下: 1朵耕、Retrofit解析1之前哨站——理解RESTful 2炫隶、Retrofit解析...
    隔壁老李頭閱讀 3,238評論 2 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)阎曹,斷路器伪阶,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 我一直都很喜歡理財博主--三公子栅贴,微信訂閱號也是每篇必讀。我雖然工作時間沒有多久熏迹,但我之前是月光族檐薯,還欠信用卡的那...
    DL諾爾閱讀 663評論 0 1
  • 中秋節(jié)剛過坛缕,家里的桌子上還堆了兩盒月餅,看著也真是發(fā)愁捆昏,一盒是小區(qū)物業(yè)發(fā)的福利赚楚,簡簡單單的包裝;另外一盒是朋...
    Yumi玉米粒閱讀 358評論 1 2
  • 是人就會有低潮期吧骗卜,不管是感情的還是事業(yè)的直晨,亦或是身體健康的低潮期搀军,這也很符合客觀規(guī)律,人生是條曲線而不是直線勇皇,...
    tong言言閱讀 523評論 2 1