国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Java設(shè)計(jì)模式005】代理模式

這篇具有很好參考價(jià)值的文章主要介紹了【Java設(shè)計(jì)模式005】代理模式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

概述

由于一些特定原因某些對(duì)象不適合或者不能直接引用目標(biāo)對(duì)象,這時(shí)就可以使用代理模式。代理模式為目標(biāo)對(duì)象提供一個(gè)代理以控制訪問對(duì)象對(duì)目標(biāo)對(duì)象的訪問。客戶端只能直接訪問代理對(duì)象,不能直接訪問目標(biāo)對(duì)象,這么做確保了目標(biāo)對(duì)象的安全。生活中一個(gè)常見的例子就是買房,客戶想買房,房東想賣房,此時(shí)客戶是客戶端,房東是服務(wù)端,但一般情況下房東不會(huì)直接帶客戶看房,這個(gè)工作通常由中介完成。還是從客戶的視角看,不論是中介還是房東,他們都是服務(wù)端,提供同樣的賣房服務(wù),也就是說客戶會(huì)將中介看成一個(gè)抽象房東,同樣能提供賣房服務(wù)。

實(shí)現(xiàn)

Java 中的代理按照代理類生成時(shí)機(jī)不同又分為靜態(tài)代理動(dòng)態(tài)代理。靜態(tài)代理代理類在編譯期就生成,而動(dòng)態(tài)代理代理類則是在 Java 運(yùn)行時(shí)動(dòng)態(tài)生成。動(dòng)態(tài)代有JDK 代理CGLib 代理兩種。

代理模式包含如下幾個(gè)角色:

  • 抽象主題(Subject)類: 通過接口或抽象類聲明真實(shí)主題和代理對(duì)象實(shí)現(xiàn)的業(yè)務(wù)方法。
  • 真實(shí)主題(Real Subject)類: 實(shí)現(xiàn)了抽象主題中的具體業(yè)務(wù),是代理對(duì)象所代表的真實(shí)對(duì)象,是最終要引用的對(duì)象。
  • 代理(Proxy)類 : 提供了與真實(shí)主題相同的接口,其內(nèi)部含有對(duì)真實(shí)主題的引用,它可以訪問、控制或擴(kuò)展真實(shí)主題的功能 。

靜態(tài)代理

實(shí)現(xiàn)的關(guān)鍵在于代理類通過組合的方式調(diào)用目標(biāo)對(duì)象的功能。以租房為例:

首先定義一個(gè)接口定義租房業(yè)務(wù)。

public interface IRentHouse {  
    void rentHouse();  
}

IRentHouse 就是抽象主題類,接著定義其實(shí)現(xiàn)類,也就是真實(shí)主題類:

public class RentHouse implements IRentHouse{
    @Override
    public void rentHouse() {
        System.out.println("房東租房");
    }
}

租房一般通過中介,所以還需要定義一個(gè)中介類作為代理,向客戶提供租房服務(wù):

public class IntermediaryProxy implements IRentHouse {  
    private RentHouse rentHouse;  
  
    public IntermediaryProxy() {  
        rentHouse = new RentHouse();  
    }  
  
    @Override  
    public void rentHouse() {  
        System.out.println("審查租房人資質(zhì)");  
        if (isQualified()) {  
            System.out.println("資質(zhì)審查通過");  
            rentHouse.rentHouse();  
            System.out.println("收取中介費(fèi)");  
        } else {  
            System.out.println("資質(zhì)審核失敗");  
        }  
    }  
  
    private boolean isQualified() {  
        return new Random().nextBoolean();  
    }  
}

在中介類中通過組合的方式完成代理,同時(shí)能夠?qū)φ{(diào)用者進(jìn)行安全檢查。最后就是客戶端;

public class Client {  
    public static void main(String[] args) {  
        // 創(chuàng)建中介代理  
        IntermediaryProxy proxy = new IntermediaryProxy();  
        proxy.rentHouse();  
    }  
}

測(cè)試結(jié)果:

審查租房人資質(zhì)
資質(zhì)審查通過
房東租房
收取中介費(fèi)

在租房這個(gè)場(chǎng)景,客戶既可以通過中介租房,也可以直接找到房東租房,因此該場(chǎng)景下的真實(shí)主題類并沒有設(shè)置為私有。

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

JDK 動(dòng)態(tài)代理

JDK 提供了動(dòng)態(tài)代理,Java 提供了一個(gè)類 Proxy,它并不是上述所說的代理對(duì)象的類,而是提供了一個(gè)創(chuàng)建代理對(duì)象的靜態(tài)方法
newProxyInstance方法)來獲取代理對(duì)象。

還是先定義業(yè)務(wù)接口:

public interface SellTickets {  
    // 賣票接口  
    void sell();  
}

然后是業(yè)務(wù)實(shí)現(xiàn)類,即真實(shí)主題類:

public class TrainStation implements SellTickets {
    public void sell() {
        System.out.println("火車站賣票");
    }
}

接著是代理類工廠:

public class ProxyFactory {  
    private final TrainStation trainStation = new TrainStation();  
  
    /*  
        newProxyInstance()方法參數(shù)說明:  
        ClassLoader loader :類加載器,用于加載代理類,使用真實(shí)對(duì)象的類加載器即可  
        Class<?>[] interfaces :真實(shí)對(duì)象所實(shí)現(xiàn)的接口,代理模式真實(shí)對(duì)象和代理對(duì)象實(shí)現(xiàn)相同的接口  
        InvocationHandler h :代理對(duì)象的調(diào)用處理程序  
    */    public Object getProxyObjet() {  
  
        return Proxy.newProxyInstance(trainStation.getClass().getClassLoader(), trainStation.getClass().getInterfaces(),  
                /*  
                    InvocationHandler中invoke方法參數(shù)說明(指定業(yè)務(wù)邏輯順序):  
                    proxy : 代理對(duì)象  
                    method : 對(duì)應(yīng)于在代理對(duì)象上調(diào)用的接口方法的 Method實(shí)例  
                    args : 代理對(duì)象調(diào)用接口方法時(shí)傳遞的實(shí)際參數(shù)  
                */                (proxy, method, args) -> {  
  
                    System.out.println("收取一定的費(fèi)用");  
                    return method.invoke(trainStation, args);  
                });  
    }  
}

最后是客戶端:

public class Client {
    public static void main(String[] args) {
        ProxyFactory factory = new ProxyFactory();
        SellTickets proxyObject = (SellTickets) factory.getProxyObjet();
        proxyObject.sell();

        System.out.println(proxyObject.getClass());
    }
}

通過反編譯看一下動(dòng)態(tài)代理類的結(jié)構(gòu):

public final class $Proxy0
extends Proxy
implements SellTickets {
    private static Method m3;

    public final void sell() {
        try {
			// h是Proxy中的一個(gè)成員變量InvocationHandler(接口),調(diào)用的invoke方法就是我們重寫實(shí)現(xiàn)的方法。
            this.h.invoke(this, m3, null);
            return;
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    static {
        try {
			
			// 獲取的是接口(SellTickets)中的sell方法。
            m3 = Class.forName("com.pcx.proxy.jdk_demo.SellTickets").getMethod("sell", new Class[0]);
          
            return;
        }
        catch (NoSuchMethodException noSuchMethodException) {
            throw new NoSuchMethodError(noSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException classNotFoundException) {
            throw new NoClassDefFoundError(classNotFoundException.getMessage());
        }
    }
}

調(diào)用流程總結(jié):

  1. 調(diào)用代理對(duì)象的sell()方法;
  2. 根據(jù)多態(tài)的特性,執(zhí)行的是代理類Proxy0中的sell()方法;
  3. Proxy0中的sell()方法調(diào)用的是InvocationHandler對(duì)象的invoke()方法;
  4. 查看接口實(shí)現(xiàn),調(diào)用具體的實(shí)現(xiàn)方法;
  5. invoke()方法通過反射執(zhí)行了真實(shí)類的對(duì)應(yīng)方法。

CGLIB 動(dòng)態(tài)代理

CGLIB是一個(gè)功能強(qiáng)大,高性能的代碼生成包。它為沒有實(shí)現(xiàn)接口的類提供代理,為 JDK 的動(dòng)態(tài)代理提供了很好的補(bǔ)充。想要使用 CGLIB 需要一下配置:

<dependency>
	<groupId>cglib</groupId>
	<artifactId>cglib</artifactId>
	<version>2.2.2</version>
</dependency>

測(cè)試代碼如下:

public class ProxyFactory implements MethodInterceptor {


    public TrainStation getProxyObject() {
        // 創(chuàng)建Enhancer類,類似于JDK代理中的Proxy
        Enhancer enhancer = new Enhancer();
        // 設(shè)置父類的字節(jié)碼對(duì)象
        enhancer.setSuperclass(TrainStation.class);
        // 設(shè)置回調(diào)函數(shù)
        enhancer.setCallback(this);

        // 創(chuàng)建代理對(duì)象
        TrainStation proxyObject = (TrainStation) enhancer.create();

        return proxyObject;
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        /*
            intercept方法參數(shù)說明:
            o : 代理對(duì)象
            method : 真實(shí)對(duì)象中的方法的Method實(shí)例
            args : 實(shí)際參數(shù)
            methodProxy :代理對(duì)象中的方法的method實(shí)例
         */
        System.out.println("收取cglib服務(wù)費(fèi)");
        // 調(diào)用目標(biāo)對(duì)象的方法
        methodProxy.invokeSuper(o, objects);
        return null;
    }
}

小結(jié)

JDK 動(dòng)態(tài)代理通過反射機(jī)制實(shí)現(xiàn),CGLIB 則采用 ASM 字節(jié)碼生成框架,使用字節(jié)碼技術(shù)生成代理類。在 JDK1.6 之前 CGLIB 比反射效率高,但是 JDK1.8 之后 JDK 代理的效率會(huì)高于 CGLIB 代理,所以如果有接口使用 JDK 動(dòng)態(tài)代理,如果沒有接口使用 CGLIB 代理,此外,CGLib 不能對(duì)聲明為 final 的類或者方法進(jìn)行代理,因?yàn)?CGLib 原理是動(dòng)態(tài)生成被代理類的子類。

動(dòng)態(tài)代理的最大優(yōu)勢(shì)是將業(yè)務(wù)接口,即抽象主題類中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個(gè)集中的方法中處理 InvocationHandler.invoke,而靜態(tài)代理需要中轉(zhuǎn)每一個(gè)方法;此外,如果接口增加了一個(gè)方法,靜態(tài)代理模式所有的真實(shí)主題類代理類都需要實(shí)現(xiàn)該方法,而動(dòng)態(tài)代理不會(huì)出現(xiàn)這樣的問題。

總結(jié)

使用場(chǎng)景

  1. 延遲初始化 (虛擬代理)。如果有一個(gè)偶爾使用的重量級(jí)服務(wù)對(duì)象,一直保持該對(duì)象運(yùn)行會(huì)消耗系統(tǒng)資源時(shí),可使用代理模式;
  2. 如果你只希望特定客戶端使用服務(wù)對(duì)象,這里的對(duì)象可以是操作系統(tǒng)中非常重要的部分,而客戶端則是各種已啟動(dòng)的程序 (包括惡意程序),此時(shí)可使用代理模式;
  3. 本地執(zhí)行遠(yuǎn)程服務(wù) (遠(yuǎn)程代理),適用于服務(wù)對(duì)象位于遠(yuǎn)程服務(wù)器上的情形;
  4. 適用于需要緩存客戶請(qǐng)求結(jié)果并對(duì)緩存生命周期進(jìn)行管理時(shí),特別是當(dāng)返回結(jié)果的體積非常大時(shí)。

優(yōu)點(diǎn)

  • 代理模式在客戶端與目標(biāo)對(duì)象之間起到一個(gè)中介和保護(hù)目標(biāo)對(duì)象的作用;
  • 代理對(duì)象可以擴(kuò)展目標(biāo)對(duì)象的功能;
  • 代理模式能將客戶端與目標(biāo)對(duì)象分離,在一定程度上降低了系統(tǒng)的耦合度;
  • 虛擬代理通過使用一個(gè)小對(duì)象來代表一個(gè)大對(duì)象,可以減少系統(tǒng)資源的消耗,對(duì)系統(tǒng)進(jìn)行優(yōu)化并提高運(yùn)行速度。

缺點(diǎn)

  • 增加了系統(tǒng)復(fù)雜度;
  • 服務(wù)響應(yīng)可能會(huì)延遲。

補(bǔ)充說明

  1. 外觀模式代理模式的相似之處在于它們都緩存了一個(gè)復(fù)雜實(shí)體并自行對(duì)其進(jìn)行初始化。區(qū)別在于代理類與其服務(wù)對(duì)象遵循同一接口,使得自己和服務(wù)對(duì)象可以互換;
  2. 裝飾這模式代理模式同樣有相似的結(jié)構(gòu),但是其意圖卻非常不同。這兩個(gè)模式的構(gòu)建都基于組合原則,也就是說一個(gè)對(duì)象應(yīng)該將部分工作委派給另一個(gè)對(duì)象。兩者之間的不同之處在于代理模式通常自行管理其服務(wù)對(duì)象的生命周期,而裝飾這模式的生成則總是由客戶端進(jìn)行控制。

往期回顧

  1. 【Java設(shè)計(jì)模式004】建造者模式
  2. 【Java設(shè)計(jì)模式003】原型模式
  3. 【Java設(shè)計(jì)模式002】工廠模式
  4. 【Java設(shè)計(jì)模式001】單例模式

文中難免會(huì)出現(xiàn)一些描述不當(dāng)之處(盡管我已反復(fù)檢查多次),歡迎在留言區(qū)指正,相關(guān)的知識(shí)點(diǎn)也可進(jìn)行分享,希望大家都能有所收獲??!如果覺得我的文章寫得還行,不妨支持一下。你的每一個(gè)轉(zhuǎn)發(fā)、關(guān)注、點(diǎn)贊、評(píng)論都是對(duì)我最大的支持!文章來源地址http://www.zghlxwxcb.cn/news/detail-661975.html

到了這里,關(guān)于【Java設(shè)計(jì)模式005】代理模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java設(shè)計(jì)模式---單例 工廠 代理模式

    單例模式是設(shè)計(jì)模式中的一種,屬于創(chuàng)建型模式。在軟件工程中,單例模式確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問點(diǎn)。這種模式常用于那些需要頻繁實(shí)例化然后引用,且創(chuàng)建新實(shí)例的開銷較大的類,例如數(shù)據(jù)庫連接池、緩存管理等。 意圖 :保證一個(gè)類僅有一個(gè)實(shí)例

    2024年01月24日
    瀏覽(29)
  • Java設(shè)計(jì)模式中的代理模式

    Java設(shè)計(jì)模式中的代理模式 代理模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,它提供了一個(gè)代理對(duì)象,以控制對(duì)其他對(duì)象的訪問。代理可以充當(dāng)中介,用于控制對(duì)真實(shí)對(duì)象的訪問。 代碼舉例演示 靜態(tài)代理: 動(dòng)態(tài)代理 區(qū)別: 靜態(tài)代理: 代理類在編譯時(shí)就已經(jīng)確定,并且需要為每個(gè)被代理的

    2024年01月25日
    瀏覽(29)
  • 【Java 設(shè)計(jì)模式】結(jié)構(gòu)型之代理模式

    代理模式(Proxy Pattern)是一種結(jié)構(gòu)型設(shè)計(jì)模式, 它允許通過一個(gè)代理對(duì)象控制對(duì)其他對(duì)象的訪問 。代理模式在訪問對(duì)象時(shí)引入了一定程度的間接性,使得可以在訪問對(duì)象前后進(jìn)行一些額外的操作。在本文中,我們將深入研究Java中代理模式的定義、結(jié)構(gòu)、使用場(chǎng)景以及如何在

    2024年01月21日
    瀏覽(23)
  • Java設(shè)計(jì)模式之代理模式--經(jīng)紀(jì)人的工作

    Java設(shè)計(jì)模式之代理模式--經(jīng)紀(jì)人的工作

    本文主要講述 代理模式 ,文中使用通俗易懂的案例,使你更好的學(xué)習(xí)本章知識(shí)點(diǎn)并理解原理,做到有道無術(shù)。 代理模式是23種設(shè)計(jì)模式中 結(jié)構(gòu)型模式 的一種,它的核心是通過代理類來完成其他對(duì)象的訪問,降低訪問者和被訪問者的耦合度,也對(duì)功能進(jìn)行了增強(qiáng)。 每個(gè)藝人

    2024年02月09日
    瀏覽(25)
  • Java復(fù)習(xí)-20-接口(3)- 代理設(shè)計(jì)模式

    Java復(fù)習(xí)-20-接口(3)- 代理設(shè)計(jì)模式

    功能:可以幫助用戶將所有的開發(fā)注意力只集中在核心業(yè)務(wù)功能的處理上。 代理模式(Proxy Pattern)是一種結(jié)構(gòu)性模式。代理模式為一個(gè)對(duì)象提供了一個(gè)替身,以控制對(duì)這個(gè)對(duì)象的訪問。即通過代理對(duì)象訪問目標(biāo)目標(biāo)對(duì)象,可以在目標(biāo)對(duì)象實(shí)現(xiàn)的基礎(chǔ)上,增強(qiáng)額外的功能操作,即

    2024年02月09日
    瀏覽(17)
  • Java 設(shè)計(jì)者模式以及與Spring關(guān)系(四) 代理模式

    Java 設(shè)計(jì)者模式以及與Spring關(guān)系(四) 代理模式

    目錄 簡(jiǎn)介: 23設(shè)計(jì)者模式以及重點(diǎn)模式 代理模式(Proxy Pattern) 靜態(tài)代理示例 spring中應(yīng)用 動(dòng)態(tài)代理 1.基于JDK的動(dòng)態(tài)代理 target.getClass().getInterfaces()作用 內(nèi)名內(nèi)部類寫法(更簡(jiǎn)潔,但不推薦) 2.基于CGLIB實(shí)現(xiàn) spring中應(yīng)用 本文是個(gè)系列一次會(huì)出兩個(gè)設(shè)計(jì)者模式作用,如果有關(guān)聯(lián)就三

    2024年01月23日
    瀏覽(92)
  • JAVA設(shè)計(jì)模式6:代理模式,用于控制對(duì)目標(biāo)對(duì)象的訪問

    JAVA設(shè)計(jì)模式6:代理模式,用于控制對(duì)目標(biāo)對(duì)象的訪問

    作者主頁 :Designer 小鄭 作者簡(jiǎn)介 :3年JAVA全棧開發(fā)經(jīng)驗(yàn),專注JAVA技術(shù)、系統(tǒng)定制、遠(yuǎn)程指導(dǎo),致力于企業(yè)數(shù)字化轉(zhuǎn)型,CSDN博客專家,阿里云社區(qū)專家博主,藍(lán)橋云課講師。 代理模式是一種常用的設(shè)計(jì)模式,它提供了一個(gè)代理對(duì)象,用于控制對(duì)目標(biāo)對(duì)象的訪問 。 在代理模式

    2024年02月07日
    瀏覽(28)
  • 【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——代理模式Proxy(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    【設(shè)計(jì)模式——學(xué)習(xí)筆記】23種設(shè)計(jì)模式——代理模式Proxy(原理講解+應(yīng)用場(chǎng)景介紹+案例介紹+Java代碼實(shí)現(xiàn))

    代理模式 為一個(gè)對(duì)象提供一個(gè)代理對(duì)象,以控制對(duì)這個(gè)對(duì)象的訪問 。即通過代理對(duì)象訪問目標(biāo)對(duì)象,這樣做的好處是:可以在不修改目標(biāo)對(duì)象代碼的基礎(chǔ)上,增強(qiáng)額外的功能操作,即擴(kuò)展目標(biāo)對(duì)象的功能 被代理的對(duì)象可以是遠(yuǎn)程對(duì)象、創(chuàng)建開銷大的對(duì)象或需要安全控制的對(duì)

    2024年02月14日
    瀏覽(59)
  • 【Java面試題】設(shè)計(jì)模式之七種結(jié)構(gòu)性模式——代理模式、適配器模式、橋接模式、裝飾模式、外觀模式、享元模式、組合模式

    目錄 一、代理模式 二、適配器模式 三、橋接模式 四、裝飾模式 五、外觀模式 六、享元模式 七、組合模式 概念: 代理模式是為其他對(duì)象提供一種以代理控制對(duì)這個(gè)對(duì)象的訪問。在某些情況下,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)

    2023年04月09日
    瀏覽(26)
  • 【Java基礎(chǔ)教程】(十五)面向?qū)ο笃?· 第九講:抽象類和接口——定義、限制與應(yīng)用的細(xì)節(jié),初窺模板設(shè)計(jì)模式、工廠設(shè)計(jì)模式與代理設(shè)計(jì)模式~

    【Java基礎(chǔ)教程】(十五)面向?qū)ο笃?· 第九講:抽象類和接口——定義、限制與應(yīng)用的細(xì)節(jié),初窺模板設(shè)計(jì)模式、工廠設(shè)計(jì)模式與代理設(shè)計(jì)模式~

    掌握 抽象類和接口的定義、使用、區(qū)別、常見設(shè)計(jì)模式; 抽象類是代碼開發(fā)中的重要組成部分,利用抽象類可以明確地定義子類需要覆寫的方法,這樣相當(dāng)于在語法程度上對(duì)子類進(jìn)行了嚴(yán)格的定義限制,代碼的開發(fā)也就更加標(biāo)準(zhǔn)。下面具體介紹抽象類的概念。 普通類可以直

    2024年02月16日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包