JAVA 設(shè)計(jì)模式之《代理模式》

一、代理模式介紹

代理模式,非常容易理解,一眼看過(guò)去大家都懂,字面意思,如果不懂稍微琢磨琢磨就懂了,我在這里舉幾個(gè)栗子?? ,以便更容易理解。

  • 賈乃亮作為一個(gè)明星,為了更專注于自己的工作,他找了一個(gè)經(jīng)紀(jì)人,幫他約綜藝、約電視劇、約電影等等。
  • 英雄聯(lián)盟打的太菜了,但是為了沖到更高的段位,在別人面前裝裝13,于是找了一個(gè)代練幫忙上分。
  • 背井離鄉(xiāng),來(lái)到一個(gè)陌生的城市打拼,不知道住在哪里怎么辦?我們可以通過(guò)中介更快的找到心儀的住所。
  • 春運(yùn)的票實(shí)在太難搶,我們只能使用搶票軟件幫我們搶票。

可以看到,在生活中,代理無(wú)處不在,無(wú)論是經(jīng)紀(jì)人、游戲代練、房產(chǎn)中介、搶票軟件,都是幫我們做事,對(duì)我們的能力進(jìn)行了擴(kuò)展。

那么在Java中使用代理模式,通過(guò)代理對(duì)象訪問(wèn)目標(biāo)對(duì)象,從而在不改變目標(biāo)對(duì)象原有代碼的基礎(chǔ)上,進(jìn)行功能的擴(kuò)展和增強(qiáng)。

目前在Java中分為三種代理模式:靜態(tài)代理、jdk動(dòng)態(tài)代理、cglib動(dòng)態(tài)代理。

二、靜態(tài)代理

靜態(tài)代理,需要代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)同一個(gè)接口。

現(xiàn)在市面上的游戲很多,我們創(chuàng)建一個(gè)接口,寫上現(xiàn)在一直很火的一款游戲,英雄聯(lián)盟


public interface Play {
    public void lol();
}

有一個(gè)對(duì)象,他叫 “有趣的靈魂200斤”,是個(gè)肥宅,名如其人對(duì)吧,他有一個(gè)愛(ài)好,就是玩、娛樂(lè),我們讓肥宅小兄弟實(shí)現(xiàn)一下這個(gè)接口,看看他是怎么玩這個(gè)游戲的。


public class FeiZhai implements Play {

    public void lol() {
        System.out.println("B鍵已扣,不死不休!");
    }
}

有一天我們的肥宅小兄弟,剛開(kāi)了新的一局英雄聯(lián)盟排位賽,突然肚子一陣作響,他看了看時(shí)間,于是拿起手機(jī)打開(kāi)餓不餓APP訂了個(gè)餐,然后繼續(xù)游戲。
那么我們的肥宅小兄弟為什么在網(wǎng)上訂餐呢,因?yàn)樗粫?huì)做飯,所以只能在網(wǎng)上訂餐,而且商家做好餐,由我們的外賣小哥送過(guò)來(lái),就可以吃了,很方便,主要是不耽誤玩游戲。


/**
 * 餓不餓App-肥宅小兄弟
 */
public class EbueProxy implements Play {

    //聲明目標(biāo)對(duì)象-為肥宅小兄弟服務(wù)
    private FeiZhai feiZhai;

    //通過(guò)構(gòu)造方法,獲取目標(biāo)對(duì)象,進(jìn)行賦值
    public EbueProxy(Play play) {
        this.feiZhai = (FeiZhai) play;
    }

    //對(duì)原來(lái)的方法進(jìn)行擴(kuò)展
    public void lol() {
        System.out.println("商家接到訂單,開(kāi)始做飯");
        System.out.println("飯做完了,外賣小哥取到餐");

        //調(diào)用目標(biāo)對(duì)象的方法
    //在不影響肥宅小兄弟玩LOL的情況下,進(jìn)行功能的拓展和增強(qiáng)。
        feiZhai.lol();
        System.out.println("外賣小哥進(jìn)行配送");
        System.out.println("叮咚!您好,您的餐,請(qǐng)慢用!");
    }
}

我們的肥宅小兄弟,為了不耽誤自己玩游戲,委托餓不餓APP送餐上門,這就是一種代理模式,讓我們運(yùn)行看一下結(jié)果。


public class main {

    public static void main(String[] args) {

        Play feiZhai = new FeiZhai();

        EbueProxy ebueProxy = new EbueProxy(feiZhai);

        ebueProxy.lol();
    }
}


商家接到訂單,開(kāi)始做飯
飯做完了,外賣小哥取到餐
B鍵已扣,不死不休!
外賣小哥進(jìn)行配送
叮咚!您好,您的餐,請(qǐng)慢用!

三、jdk 動(dòng)態(tài)代理

又是充滿希望的一天,今天我們的肥宅小兄弟不想玩LOL了,他熟練的拿起手機(jī),打開(kāi)和平精英,準(zhǔn)備吃(kuai)雞(di)之旅。

我們給接口類加一個(gè)方法


public interface Play {
    public void lol();

    public void chiJi();
}

再具體實(shí)現(xiàn)一下


public class FeiZhai implements Play {

    public void lol() {
        System.out.println("B鍵已扣,不死不休!");
    }

    public void chiJi() {
        System.out.println("人體描邊說(shuō)的就是在下了!");
    }
}

到飯點(diǎn)了,又是和昨天一樣的情況,我們?cè)賹懸惶状a,委托餓不餓APP幫我們送下餐


/**
 * 餓不餓App
 */
public class EbueProxy implements Play {

    //聲明目標(biāo)對(duì)象-為肥宅小兄弟服務(wù)
    private FeiZhai feiZhai;

    //通過(guò)構(gòu)造方法,獲取目標(biāo)對(duì)象,進(jìn)行賦值
    public EbueProxy(Play play){
        this.feiZhai = (FeiZhai) play;
    }

    //對(duì)原來(lái)的方法進(jìn)行擴(kuò)展
    public void lol() {
        System.out.println("商家接到訂單,開(kāi)始做飯");
        System.out.println("飯做完了,外賣小哥取到餐");

    //調(diào)用目標(biāo)對(duì)象的方法
    //在不影響肥宅小兄弟玩LOL的情況下,進(jìn)行功能的拓展和增強(qiáng)。
        feiZhai.lol();
        System.out.println("外賣小哥進(jìn)行配送");
        System.out.println("叮咚!您好,您的餐,請(qǐng)慢用!");
    }

    //對(duì)原來(lái)的方法進(jìn)行擴(kuò)展
    public void chiJi() {
        System.out.println("商家接到訂單,開(kāi)始做飯");
        System.out.println("飯做完了,外賣小哥取到餐");

    //調(diào)用目標(biāo)對(duì)象的方法
    //在不影響肥宅小兄弟玩吃雞的情況下,進(jìn)行功能的拓展和增強(qiáng)。
        feiZhai.chiJi();
        System.out.println("外賣小哥進(jìn)行配送");
        System.out.println("叮咚!您好,您的餐,請(qǐng)慢用!");
    }
}

看到這里的小伙伴們,應(yīng)該都發(fā)現(xiàn)問(wèn)題了,如果肥宅小兄弟每天換個(gè)游戲,那我們豈不是要累死了,而且現(xiàn)在還只是1個(gè)肥宅小兄弟,如果是2個(gè)、3個(gè)、100個(gè)呢,難道我們要?jiǎng)?chuàng)建不同的 EbueProxy 代理類么?

要知道現(xiàn)在咱們代碼中的 EbueProxy 類,只為 FeiZhai 這個(gè)類提供代理服務(wù),相當(dāng)于定制版,如果我想為FeiZhai1、FeiZhai2提供代理服務(wù),我還要再寫2個(gè)代理類,如果這個(gè)時(shí)候Play接口新加了幾個(gè)方法,我們又要去維護(hù)實(shí)現(xiàn)了Play接口的這些類,很不方便。

本著最少的代碼干最多的事這種原則,我們不能接受這樣的結(jié)果。

這個(gè)時(shí)候我們就要使用 jdk動(dòng)態(tài)代理 了,我們創(chuàng)建一個(gè)類 EbueDynamicProxy,實(shí)現(xiàn) InvocationHandler 接口,重寫 invoke 方法。


/**
 * 餓不餓App-動(dòng)態(tài)代理
 */
public class EbueDynamicProxy implements InvocationHandler {

    //注意這里,我們換成了Object,意味著我們可以接受不同的目標(biāo)對(duì)象
    private Object object;

    //通過(guò)構(gòu)造方法,獲取目標(biāo)對(duì)象,進(jìn)行賦值
    public EbueDynamicProxy(Object object){
        this.object = object;
    }

    /**
     *
     * 每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn)InvocationHandler這個(gè)接口,并且每個(gè)代理類的實(shí)例都關(guān)聯(lián)到了一個(gè)handler,
     * 當(dāng)我們通過(guò)代理對(duì)象調(diào)用一個(gè)方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)為由InvocationHandler這個(gè)接口的 invoke 方法來(lái)進(jìn)行調(diào)用。
     * InvocationHandler這個(gè)接口的唯一一個(gè)方法 invoke 方法:
     * 該方法接收3個(gè)參數(shù):
     * proxy:  指代我們所代理的那個(gè)目標(biāo)對(duì)象
     * method: 指代的是我們所要調(diào)用目標(biāo)對(duì)象的某個(gè)方法的Method對(duì)象
     * args:  指代的是調(diào)用目標(biāo)對(duì)象某個(gè)方法時(shí)接受的參數(shù)
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("商家接到訂單,開(kāi)始做飯");
        System.out.println("飯做完了,外賣小哥取到餐");

        Object obj = method.invoke(object, args);

        System.out.println("外賣小哥進(jìn)行配送");
        System.out.println("叮咚!您好,肥先生的餐,請(qǐng)慢用!\n");
        return obj;
    }
}

靜態(tài)代理和jdk動(dòng)態(tài)代理最大的區(qū)別就是,jdk動(dòng)態(tài)代理是jvm幫我們生成了代理類。

至于jvm怎么生成的我們目前不需要去操心,我們看看我們?cè)趺从|發(fā)去讓jvm生成。


public class main {

    public static void main(String[] args) {

        //創(chuàng)建一個(gè)目標(biāo)對(duì)象的實(shí)例
        Play feizhai = new FeiZhai();

        //創(chuàng)建一個(gè)與目標(biāo)對(duì)象相關(guān)聯(lián)的InvocationHandler
        InvocationHandler ebueDynamicProxy = new EbueDynamicProxy(feizhai);

        //獲取目標(biāo)對(duì)象的類加載器
        ClassLoader classLoader = feizhai.getClass().getClassLoader();

        //獲取目標(biāo)對(duì)象的所有接口
        Class[] interfaces = feizhai.getClass().getInterfaces();

        //Proxy.newProxyInstance:返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用
        Play feiZhaiProxy = (Play) Proxy.newProxyInstance(classLoader, interfaces, ebueDynamicProxy);

        //英雄聯(lián)盟
        feiZhaiProxy.lol();

        //吃雞
        feiZhaiProxy.chiJi();

    }
}

運(yùn)行一下看看輸出


商家接到訂單,開(kāi)始做飯
飯做完了,外賣小哥取到餐
B鍵已扣,不死不休!
外賣小哥進(jìn)行配送
叮咚!您好,您的餐,請(qǐng)慢用!

商家接到訂單,開(kāi)始做飯
飯做完了,外賣小哥取到餐
人體描邊說(shuō)的就是在下了!
外賣小哥進(jìn)行配送
叮咚!您好,您的餐,請(qǐng)慢用!

是不是很簡(jiǎn)單,接下來(lái)我們分析一下原理,知道怎么做還不夠,還得知道為什么能這么做。

通過(guò)靜態(tài)代理,我們很明顯可以看到,動(dòng)態(tài)代理是由靜態(tài)代理演化而來(lái),之前我們手寫代理類,有幾個(gè)目標(biāo)對(duì)象就寫幾個(gè)代理類,目標(biāo)對(duì)象里有幾個(gè)方法,代理類里就寫幾個(gè)方法,現(xiàn)在換成jdk動(dòng)態(tài)代理,我們就靠jvm來(lái)動(dòng)態(tài)生成代理類,我們只要需要實(shí)現(xiàn) InvocationHandler 接口,重寫 invoke 方法,添加上需要擴(kuò)展的功能代碼,然后交給jvm就可以了,jvm會(huì)幫我們?cè)诔绦蜻\(yùn)行時(shí)生成代理類,代理類的名稱為$Proxy0、$Proxy1、$Proxy2 …以此類推。

這個(gè)時(shí)候我們想看看jvm生成的代理類是什么樣的怎么辦?我們?cè)趍ain方法里面加上這樣一行代碼,這樣jvm生成的代理類就會(huì)出現(xiàn)在項(xiàng)目里的com.sun.proxy這個(gè)目錄下面了。


public class main {

    public static void main(String[] args) {

        //這行代碼的意思是將JDK動(dòng)態(tài)代理生成的class文件保存到本地
        //作者本地jdk1.8親測(cè)可用,有人說(shuō)新版本的jdk用下面一行好使,不知道是多新的版本,如果有人用了發(fā)現(xiàn)沒(méi)生成,可以換下面這行代碼試試!
        //System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        //創(chuàng)建一個(gè)目標(biāo)對(duì)象的實(shí)例
        Play feizhai = new FeiZhai();

        //創(chuàng)建一個(gè)與目標(biāo)對(duì)象相關(guān)聯(lián)的InvocationHandler
        InvocationHandler ebueDynamicProxy = new EbueDynamicProxy(feizhai);

        //獲取目標(biāo)對(duì)象的類加載器
        ClassLoader classLoader = feizhai.getClass().getClassLoader();

        //獲取目標(biāo)對(duì)象的所有接口
        Class[] interfaces = feizhai.getClass().getInterfaces();

        //Proxy.newProxyInstance:返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用
        Play feiZhaiProxy = (Play) Proxy.newProxyInstance(classLoader, interfaces, ebueDynamicProxy);

        //英雄聯(lián)盟
        feiZhaiProxy.lol();

        //吃雞
        feiZhaiProxy.chiJi();

    }
}

我們運(yùn)行一下,果然生成了,文件名也是$Proxy開(kāi)頭

代理類

我們?cè)倏纯碿lass文件里面的代碼是什么樣的


package com.sun.proxy;

import com.test.proxy.Play;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Play {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3;
    private static Method m4;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void chiJi() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void lol() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("com.test.proxy.Play").getMethod("chiJi");
            m4 = Class.forName("com.test.proxy.Play").getMethod("lol");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

我們看到在這個(gè)類里面,寫了一個(gè)靜態(tài)代碼塊,這里的m1、m2、m3等等,都是使用了反射找到了對(duì)應(yīng)的Method對(duì)象。


static {
    try {
        m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
        m2 = Class.forName("java.lang.Object").getMethod("toString");
        m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        m3 = Class.forName("com.test.proxy.Play").getMethod("lol");
        m4 = Class.forName("com.test.proxy.Play").getMethod("chiJi");
    } catch (NoSuchMethodException var2) {
        throw new NoSuchMethodError(var2.getMessage());
    } catch (ClassNotFoundException var3) {
        throw new NoClassDefFoundError(var3.getMessage());
    }
}

然后我們?cè)僬业轿覀儗懙膌ol方法,我們拿這個(gè)進(jìn)行舉例說(shuō)明。


public final void lol() throws  {
    try {
        super.h.invoke(this, m3, (Object[])null);
    } catch (RuntimeException | Error var2) {
        throw var2;
    } catch (Throwable var3) {
        throw new UndeclaredThrowableException(var3);
    }
}

可以看到代碼很簡(jiǎn)單,主要就是這么一行代碼
super.h.invoke(this, m3, (Object[])null);
這行代碼的意思就是調(diào)用當(dāng)前類的父類的h變量的invoke方法。這么讀發(fā)現(xiàn)有點(diǎn)繞是不是,沒(méi)事,我們來(lái)剖析一下看看當(dāng)前類的父類是誰(shuí)?當(dāng)前類的父類的h變量又是什么?調(diào)用這個(gè)invoke方法又有什么用?來(lái)上代碼。


import com.test.proxy.Play;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Play  

從上面這段代碼我們可以看到,$Proxy0代理類繼承了Proxy類,并且實(shí)現(xiàn)了我們寫的Play接口,這下明白了,當(dāng)前類的父類就是Proxy類。


public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    private static final Class<?>[] constructorParams = { InvocationHandler.class };

    private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    //看這里
    protected InvocationHandler h;

}

再看上面這段代碼,h變量就是InvocationHandler類,那么super.h.invoke方法,就相當(dāng)于是調(diào)用了proxy的h變量的invoke方法,還記得invoke方法是什么嗎,就是我們寫的EbueDynamicProxy類里面的invoke方法,執(zhí)行的就是這個(gè)方法。至于什么時(shí)候把EbueDynamicProxy類賦值給了h變量,我們?cè)趍ain方法里不是寫了Proxy.newProxyInstance了,就是在那個(gè)時(shí)候,把EbueDynamicProxy傳過(guò)去的。


接下來(lái)我們來(lái)粗略看一下cglib動(dòng)態(tài)代理。

如果你使用了Spring框架,就不用單獨(dú)引入cglib了,因?yàn)镾pring集成了cglib。

接下來(lái)我們創(chuàng)建一個(gè)普通的類,寫上一個(gè)方法。


public class HelloFeiZhai {

    public void hello(){
        System.out.println("你好,肥宅!");
    }

}

然后我們開(kāi)始為這個(gè)類創(chuàng)建動(dòng)態(tài)代理,首先要?jiǎng)?chuàng)建一個(gè)類,實(shí)現(xiàn)MethodInterceptor接口,并且重寫intercept方法。


public class CglibDynamicProxy implements MethodInterceptor {

    /**
     * 增強(qiáng)代碼
     * @param object        被代理的對(duì)象
     * @param method        代理的方法
     * @param objects       方法參數(shù)
     * @param methodProxy   cglib方法代理對(duì)象
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("你好,我叫 有趣的靈魂200斤");

        Object obj = methodProxy.invokeSuper(object, objects);

        System.out.println("我好你******");

        return obj;
    }
}

然后看看main方法


public static void main(String[] args) {

    CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy();

    //Enhancer是cglib的字節(jié)碼增強(qiáng)器,用來(lái)創(chuàng)建動(dòng)態(tài)代理類
    Enhancer enhancer = new Enhancer();

    //指定要代理的業(yè)務(wù)類(即:為要生成的代理類指定父類)
    enhancer.setSuperclass(HelloFeiZhai.class);

    //設(shè)置回調(diào):對(duì)于代理類上所有方法的調(diào)用,都會(huì)調(diào)用CallBack,而Callback則需要實(shí)現(xiàn)MethodInterceptor接口的intercept()方法進(jìn)行攔截
    enhancer.setCallback(cglibDynamicProxy);

    // 創(chuàng)建動(dòng)態(tài)代理類對(duì)象并返回
    HelloFeiZhai helloFeiZhai = (HelloFeiZhai)enhancer.create();

    // 調(diào)用
    helloFeiZhai.hello();

}

運(yùn)行結(jié)果:


你好,我叫 有趣的靈魂200斤
你好,肥宅!
我好你*****

四、cglib 動(dòng)態(tài)代理

cglib的源碼確實(shí)比較復(fù)雜,我自己還有好多地方不明白,就不拿出來(lái)誤導(dǎo)大家了,我粗略的說(shuō)一下原理:通過(guò)字節(jié)碼技術(shù)為一個(gè)類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類方法的調(diào)用,順勢(shì)織入橫切邏輯。

五、總結(jié)

jdk動(dòng)態(tài)代理在老的java版本中,效率不盡人意,是比cglib要慢的,但是在jdk1.8版本,據(jù)大佬說(shuō),jdk動(dòng)態(tài)代理已經(jīng)是比cglib要快了。

在這篇文章中我們講了java設(shè)計(jì)模式之一的《代理模式》,介紹了現(xiàn)在java中的三種代理模式(靜態(tài)代理、jdk動(dòng)態(tài)代理、cglib動(dòng)態(tài)代理),而且分別演示了三種代理模式的使用方法、說(shuō)明了它們之間的關(guān)系和區(qū)別,以及優(yōu)缺點(diǎn)。

如果寫的有什么問(wèn)題,歡迎大家在底下評(píng)論指正,我會(huì)及時(shí)采納和修改,感謝!

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Java設(shè)計(jì)模式——代理模式 代理模式主要分為接口,委托類,代理類 接口:規(guī)定具體方法委托類:實(shí)現(xiàn)接口,完成具體的...
    vczyh閱讀 738評(píng)論 0 0
  • 原文連接 簡(jiǎn)介 Java編程的目標(biāo)是實(shí)現(xiàn)現(xiàn)實(shí)不能完成的,優(yōu)化現(xiàn)實(shí)能夠完成的,是一種虛擬技術(shù)。生活中的方方面面都可以...
    zjk_00閱讀 399評(píng)論 0 0
  • 設(shè)計(jì)模式是語(yǔ)言的表達(dá)方式,它能讓語(yǔ)言輕便而富有內(nèi)涵、易讀卻功能強(qiáng)大。代理模式在Java中十分常見(jiàn),有為擴(kuò)展某些類的...
    CatalinaX閱讀 496評(píng)論 0 0
  • 最近看到一篇關(guān)于講代理的文章,接觸到了一些jdk動(dòng)態(tài)代理,然后寫一篇文章加深下記憶。主要講靜態(tài)代理和動(dòng)態(tài)代理,通俗...
    浪漫宇宙與人間日常閱讀 363評(píng)論 0 0
  • 定義 代理模式是對(duì)象的結(jié)構(gòu)模式。代理模式給某一個(gè)對(duì)象提供代理對(duì)象,并由代理對(duì)象控制對(duì)源對(duì)象的引用。 代理模式的結(jié)構(gòu)...
    步積閱讀 6,626評(píng)論 0 1

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