最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java代理模式之靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn)

 更新時(shí)間:2023年06月27日 09:16:31   作者:蜀山劍客李沐白  
代理模式是一種常用的設(shè)計(jì)模式,它允許通過(guò)引入一個(gè)代理對(duì)象來(lái)控制對(duì)目標(biāo)對(duì)象的訪問(wèn),在Java中,代理模式被廣泛應(yīng)用,它可以提供額外的功能,如權(quán)限檢查、緩存、日志記錄等,本文將介紹靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn),需要的朋友可以參考下

1. 代理模式的定義

代理模式(Proxy Pattern)是指通過(guò)代理對(duì)象控制對(duì)目標(biāo)對(duì)象的訪問(wèn),并在不改變目標(biāo)對(duì)象的情況下添加額外的功能或控制訪問(wèn)。代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)相同的接口,使得客戶端可以通過(guò)代理對(duì)象間接地訪問(wèn)目標(biāo)對(duì)象。

代理模式屬于結(jié)構(gòu)型設(shè)計(jì)模式,它在系統(tǒng)中引入了一個(gè)代理對(duì)象,該對(duì)象代替了客戶端直接訪問(wèn)目標(biāo)對(duì)象,從而可以在目標(biāo)對(duì)象的基礎(chǔ)上增加一些額外的功能或控制訪問(wèn)。

2. 代理模式的原理

代理模式的核心思想是引入一個(gè)代理對(duì)象來(lái)控制對(duì)目標(biāo)對(duì)象的訪問(wèn)。代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)相同的接口,使得客戶端可以通過(guò)代理對(duì)象間接地訪問(wèn)目標(biāo)對(duì)象。代理對(duì)象負(fù)責(zé)處理客戶端的請(qǐng)求,并在必要時(shí)將請(qǐng)求轉(zhuǎn)發(fā)給目標(biāo)對(duì)象。在這個(gè)過(guò)程中,代理對(duì)象可以添加額外的邏輯,如權(quán)限檢查、緩存、日志記錄等。

代理模式的主要角色有:

  • 抽象主題(Subject):定義了代理對(duì)象和目標(biāo)對(duì)象的共同接口,在Java中通常是一個(gè)接口或抽象類(lèi)。
  • 目標(biāo)對(duì)象(RealSubject):定義了代理對(duì)象所代表的真實(shí)對(duì)象,是業(yè)務(wù)邏輯的具體執(zhí)行者。
  • 代理對(duì)象(Proxy):持有對(duì)目標(biāo)對(duì)象的引用,并實(shí)現(xiàn)了與目標(biāo)對(duì)象相同的接口,在方法調(diào)用前后進(jìn)行額外操作。

代理模式的工作流程如下:

  • 客戶端向代理對(duì)象發(fā)送請(qǐng)求。
  • 代理對(duì)象收到請(qǐng)求后,可以在請(qǐng)求被轉(zhuǎn)發(fā)給目標(biāo)對(duì)象之前或之后執(zhí)行一些額外的邏輯。
  • 代理對(duì)象將請(qǐng)求轉(zhuǎn)發(fā)給目標(biāo)對(duì)象。
  • 目標(biāo)對(duì)象執(zhí)行具體的業(yè)務(wù)邏輯并返回結(jié)果。
  • 代理對(duì)象可以在目標(biāo)對(duì)象返回結(jié)果之前或之后執(zhí)行一些額外的操作。
  • 代理對(duì)象將結(jié)果返回給客戶端。

通過(guò)引入代理對(duì)象,代理模式可以控制對(duì)目標(biāo)對(duì)象的訪問(wèn),并在不改變目標(biāo)對(duì)象的情況下添加額外的功能或控制訪問(wèn)。

3. 代理模式的實(shí)現(xiàn)方式

在Java中,代理模式主要有兩種實(shí)現(xiàn)方式:靜態(tài)代理和動(dòng)態(tài)代理。

3.1 靜態(tài)代理

靜態(tài)代理是指在編譯時(shí)就已經(jīng)確定了代理對(duì)象和目標(biāo)對(duì)象的關(guān)系,代理類(lèi)是通過(guò)手動(dòng)編寫(xiě)代碼來(lái)實(shí)現(xiàn)的。在靜態(tài)代理中,代理類(lèi)和目標(biāo)類(lèi)都實(shí)現(xiàn)相同的接口,代理類(lèi)持有目標(biāo)對(duì)象,并在方法調(diào)用前后進(jìn)行額外的操作。

靜態(tài)代理的工作原理如下:

  • 定義一個(gè)接口(或抽象類(lèi))作為目標(biāo)接口,目標(biāo)對(duì)象實(shí)現(xiàn)這個(gè)接口。
  • 創(chuàng)建一個(gè)代理類(lèi),實(shí)現(xiàn)目標(biāo)接口,并持有目標(biāo)對(duì)象的引用。
  • 在代理類(lèi)中重寫(xiě)目標(biāo)接口的方法,在方法調(diào)用前后執(zhí)行需要的額外操作。
  • 客戶端使用代理對(duì)象來(lái)訪問(wèn)目標(biāo)對(duì)象。

靜態(tài)代理的特點(diǎn):

  • 需要手動(dòng)編寫(xiě)代理類(lèi),工作量較大。
  • 目標(biāo)對(duì)象必須實(shí)現(xiàn)接口。
  • 代理類(lèi)和目標(biāo)類(lèi)的關(guān)系在編譯時(shí)就確定了,無(wú)法動(dòng)態(tài)改變。

靜態(tài)代理的應(yīng)用場(chǎng)景:

  • 安全控制:代理類(lèi)可以在調(diào)用目標(biāo)方法前進(jìn)行權(quán)限檢查等安全控制。
  • 遠(yuǎn)程調(diào)用:代理類(lèi)可以封裝網(wǎng)絡(luò)通信相關(guān)的細(xì)節(jié),使得調(diào)用遠(yuǎn)程方法就像調(diào)用本地方法一樣簡(jiǎn)單。
  • 性能監(jiān)控:代理類(lèi)可以收集方法的執(zhí)行時(shí)間、調(diào)用次數(shù)等信息,用于性能監(jiān)控和統(tǒng)計(jì)分析。

下面是一個(gè)簡(jiǎn)單的靜態(tài)代理的示例代碼:

// 定義接口
public interface Image {
    void display();
}
// 目標(biāo)類(lèi)
public class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }
    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }
    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}
// 代理類(lèi)
public class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;
    public ImageProxy(String filename) {
        this.filename = filename;
    }
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}
// 測(cè)試類(lèi)
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 使用代理對(duì)象顯示圖片
        Image image = new ImageProxy("test.jpg");
        image.display();
        // 圖片已加載,直接顯示,無(wú)需重新加載
        image.display();
    }
}

在上面的示例中,Image 是一個(gè)接口,RealImage 是目標(biāo)類(lèi),負(fù)責(zé)加載和顯示圖片。ImageProxy 是代理類(lèi),通過(guò)持有目標(biāo)類(lèi)的引用,在需要時(shí)創(chuàng)建并使用目標(biāo)類(lèi)。ProxyPatternDemo 是一個(gè)測(cè)試類(lèi),用于演示靜態(tài)代理的使用。

在測(cè)試類(lèi)中,首先創(chuàng)建一個(gè)代理對(duì)象 ImageProxy,并調(diào)用 display() 方法顯示圖片。代理對(duì)象會(huì)在第一次調(diào)用 display() 方法時(shí),創(chuàng)建真實(shí)對(duì)象 RealImage 并調(diào)用其 display() 方法加載和顯示圖片。在后續(xù)調(diào)用 display() 方法時(shí),代理對(duì)象直接調(diào)用真實(shí)對(duì)象的 display() 方法,無(wú)需重新加載圖片。

靜態(tài)代理的缺點(diǎn)是需要手動(dòng)編寫(xiě)代理類(lèi),工作量較大。如果接口中的方法較多或頻繁變動(dòng),就需要頻繁修改代理類(lèi)的代碼,增加了維護(hù)的難度。此外,靜態(tài)代理的代理類(lèi)和目標(biāo)類(lèi)之間存在緊耦合關(guān)系,一旦目標(biāo)類(lèi)發(fā)生變化,代理類(lèi)也需要相應(yīng)修改。

為了解決靜態(tài)代理的缺點(diǎn),Java還提供了動(dòng)態(tài)代理機(jī)制。

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

動(dòng)態(tài)代理是指在運(yùn)行時(shí)生成代理對(duì)象,而無(wú)需手動(dòng)編寫(xiě)代理類(lèi)。Java的動(dòng)態(tài)代理機(jī)制是基于反射實(shí)現(xiàn)的,通過(guò)使用java.lang.reflect.Proxy類(lèi)和java.lang.reflect.InvocationHandler接口來(lái)實(shí)現(xiàn)動(dòng)態(tài)代理。

在動(dòng)態(tài)代理中,代理類(lèi)的創(chuàng)建和方法調(diào)用都是在運(yùn)行時(shí)完成的。代理對(duì)象是在內(nèi)存中動(dòng)態(tài)創(chuàng)建的,并實(shí)現(xiàn)了目標(biāo)對(duì)象的接口,同時(shí)持有目標(biāo)對(duì)象的引用。在方法調(diào)用時(shí),代理對(duì)象通過(guò)調(diào)用InvocationHandler接口中的方法來(lái)處理請(qǐng)求,可以在方法調(diào)用前后執(zhí)行額外的操作。

動(dòng)態(tài)代理的工作原理如下:

  • 定義一個(gè)接口,作為目標(biāo)接口。
  • 創(chuàng)建一個(gè)InvocationHandler接口的實(shí)現(xiàn)類(lèi),該類(lèi)負(fù)責(zé)處理方法調(diào)用并執(zhí)行額外的操作。
  • 使用Proxy類(lèi)的靜態(tài)方法newProxyInstance()生成代理對(duì)象,同時(shí)指定目標(biāo)對(duì)象和InvocationHandler。
  • 客戶端使用代理對(duì)象來(lái)訪問(wèn)目標(biāo)對(duì)象的方法。

動(dòng)態(tài)代理的特點(diǎn):

  • 不需要手動(dòng)編寫(xiě)代理類(lèi),代理對(duì)象在運(yùn)行時(shí)動(dòng)態(tài)生成。
  • 目標(biāo)對(duì)象可以不實(shí)現(xiàn)接口,只需定義目標(biāo)對(duì)象的共同接口。
  • 代理對(duì)象和目標(biāo)對(duì)象的關(guān)系在運(yùn)行時(shí)確定,可以動(dòng)態(tài)改變。

動(dòng)態(tài)代理的應(yīng)用場(chǎng)景:

  • AOP(面向切面編程):動(dòng)態(tài)代理可以在目標(biāo)方法執(zhí)行前后執(zhí)行額外的操作,如權(quán)限檢查、事務(wù)管理等。它是實(shí)現(xiàn)AOP的一種常見(jiàn)方式。
  • 延遲加載:動(dòng)態(tài)代理可以在目標(biāo)方法被調(diào)用時(shí)才進(jìn)行加載和初始化,實(shí)現(xiàn)延遲加載的效果。
  • 日志記錄:動(dòng)態(tài)代理可以在目標(biāo)方法執(zhí)行前后記錄日志信息。

下面是一個(gè)簡(jiǎn)單的動(dòng)態(tài)代理的示例代碼:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定義接口
interface Image {
    void display();
}
// 目標(biāo)類(lèi)
class RealImage implements Image {
    private String filename;
    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }
    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }
    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}
// InvocationHandler 實(shí)現(xiàn)類(lèi)
class ImageInvocationHandler implements InvocationHandler {
    private Object target;
    public ImageInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After method: " + method.getName());
        return result;
    }
}
// 測(cè)試類(lèi)
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 創(chuàng)建目標(biāo)對(duì)象
        Image realImage = new RealImage("test.jpg");
        // 創(chuàng)建 InvocationHandler 實(shí)例
        ImageInvocationHandler handler = new ImageInvocationHandler(realImage);
        // 創(chuàng)建代理對(duì)象
        Image imageProxy = (Image) Proxy.newProxyInstance(Image.class.getClassLoader(),
                new Class[]{Image.class}, handler);
        // 使用代理對(duì)象顯示圖片
        imageProxy.display();
    }
}

在上面的示例中,Image 是一個(gè)接口,RealImage 是目標(biāo)類(lèi),負(fù)責(zé)加載和顯示圖片。ImageInvocationHandlerInvocationHandler接口的實(shí)現(xiàn)類(lèi),用于處理方法調(diào)用并執(zhí)行額外的操作。ProxyPatternDemo 是一個(gè)測(cè)試類(lèi),用于演示動(dòng)態(tài)代理的使用。

在測(cè)試類(lèi)中,首先創(chuàng)建一個(gè)目標(biāo)對(duì)象 RealImage,然后創(chuàng)建一個(gè) ImageInvocationHandler 實(shí)例,并將目標(biāo)對(duì)象傳入構(gòu)造函數(shù)。接下來(lái),通過(guò)調(diào)用 Proxy 類(lèi)的 newProxyInstance() 方法來(lái)生成代理對(duì)象。最后,使用代理對(duì)象調(diào)用 display() 方法顯示圖片。

在方法調(diào)用時(shí),代理對(duì)象會(huì)調(diào)用 InvocationHandler 接口中的 invoke() 方法處理方法調(diào)用。在示例中,我們?cè)?invoke() 方法中實(shí)現(xiàn)了打印方法名的額外操作,并通過(guò)反射調(diào)用目標(biāo)對(duì)象的方法。

以上就是Java代理模式之靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn)的詳細(xì)內(nèi)容,更多關(guān)于Java 靜態(tài)與動(dòng)態(tài)代理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

新平| 武清区| 巴彦淖尔市| 镇安县| 大埔县| 汶上县| 句容市| 讷河市| 木兰县| 张掖市| 阳朔县| 伊川县| 绥棱县| 蒲城县| 郑州市| 辉县市| 和平区| 中山市| 哈尔滨市| 建德市| 两当县| 武宣县| 兰考县| 南宫市| 邵东县| 碌曲县| 瑞昌市| 呼图壁县| 德阳市| 高碑店市| 珠海市| 张掖市| 固阳县| 当涂县| 定州市| 临邑县| 贡嘎县| 张北县| 大庆市| 濉溪县| 石台县|