1. 程式人生 > >代理模式(Proxy Pattern)

代理模式(Proxy Pattern)

簡述

代理模式是一種結構型設計模式,代理模式主要包含三種角色:抽象物件角色、目標物件角色、代理物件角色,代理模式主要通過抽象物件角色來為目標物件提供一個代理物件,並由代理物件控制對原物件的引用,提供了一種對目標物件另外的訪問方式,這樣做的好處是,可以在目標物件實現的基礎上,增加豐富額外的功能,即擴充套件目標物件的功能。

分類

代理模式主要分為兩大類:靜態代理模式和動態代理模式,其中動態代理模式又可分為JDK動態代理和cglib動態代理,下面對各種代理模式做詳細介紹。

靜態代理模式

靜態代理是簡單代理模式,是由程式設計師編寫的代理類,並在程式執行前就編譯好的,而非程式動態產生代理類,這就是所謂的靜態。也就是說需要提前定義介面或者父類,目標物件與代理物件一起實現相同的介面或者是繼承相同父類。

例項

系統有一個列印的目標類,但是每次操作列印時需要增加日誌,而新增日誌這個功能在列印這個目標類中不存在,因此可以通過代理類在實現列印的同時增加日誌功能。
程式碼如下:

/**
 * @Author: dong
 * @Project: DesignPatterns
 * @Description: 抽象的列印介面
 * @Date: Created in 下午11:04 2018/7/21
 * @Modified By:
 */
public interface Print {
    public void print();
}

/**
 * @Author: dong
 * @Project
: DesignPatterns * @Description: 目標類 * @Date: Created in 下午11:07 2018/7/21 * @Modified By: */
public class PrintReal implements Print { @Override public void print() { System.out.println("print..."); } } /** * @Author: dong * @Project: DesignPatterns * @Description: 代理類 * @Date
: Created in 下午11:04 2018/7/21 * @Modified By: */
public class PrintProxy implements Print { private PrintReal print; public PrintProxy(PrintReal print){ super(); this.print = print; } @Override public void print() { System.out.println("log:XXX在YYY時間開始列印..."); print.print(); System.out.println("log:XXX在MMM時間結束列印..."); } } /** * @Author: dong * @Project: DesignPatterns * @Description: 測試類 * @Date: Created in 下午11:20 2018/7/21 * @Modified By: */ public class TestProxy { public static void main(String[] args) { PrintReal printReal = new PrintReal(); Print print = new PrintProxy(printReal); print.print(); } }

總結:

優點是:可以做到在不修改目標物件的功能前提下,對目標功能擴充套件。
缺點是:因為代理物件需要與目標物件實現一樣的介面,所以會有很多代理類,同時,一旦介面增加方法,目標物件與代理物件都要維護。

動態代理

代理類在程式執行時建立的代理方式被成為動態代理。上例中的PrintProxy在程式執行之前就已經編譯完成。然而動態代理,代理類並不是在Java程式碼中定義的,而是在執行時根據我們在Java程式碼中的“指示”動態生成的。相比於靜態代理, 動態代理的優勢在於可以很方便的對代理類的函式進行統一的處理,而不用修改每個代理類中的方法。
動態代理擴充套件了靜態代理的不足,例如有多個目標類,其中需要的擴充套件方法差不多一致,即僅呼叫的目標類不同。也就是說,多個目標類對應一個代理類,共享拓展功能,動態呼叫所需主題,這樣可以大大減小了程式規模,這就是動態代理模式的特點。

JDK動態代理

JDK中生成代理物件的API,JDK實現代理需要使用newProxyInstance方法:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h );

該方法是在Proxy類中是靜態方法,且接收的三個引數依次為:
ClassLoader loader:指定當前目標物件使用類載入器,獲取載入器的方法是固定的。
Class<?>[] interfaces:目標物件實現的介面的型別,使用泛型方式確認型別。
InvocationHandler:指定動態處理器,執行目標物件的方法時,會觸發事件處理器的方法。

具體過程如下:
1、定義一個事件管理器類實現invocationHandle介面,並重寫invoke(代理類,被代理的方法,方法的引數列表)方法;
2、實現被代理類及其實現的介面;
3、呼叫Proxy的靜態方法newProxyInstance(類載入器,類實現的介面,事務處理器物件),生成一個代理例項;
4、通過該代理例項呼叫方法。
程式碼如下:

/**
 * @Author: dong
 * @Project: DesignPatterns
 * @Description: 抽象的列印介面
 * @Date: Created in 下午11:34 2018/7/21
 * @Modified By:
 */
public interface Print {
    public void print();
}


/**
 * @Author: dong
 * @Project: DesignPatterns
 * @Description: 目標類
 * @Date: Created in 下午11:37 2018/7/21
 * @Modified By:
 */
public class PrintReal implements Print {
    @Override
    public void print() {
        System.out.println("print...");
    }
}


/**
 * @Author: dong
 * @Project: DesignPatterns
 * @Description:
 * @Date: Created in 下11:40 2018/7/21
 * @Modified By:
 */
public class ProxyPrint implements InvocationHandler {
    private Object target;
    public ProxyPrint(Object object) {
        super();
        this.target = object;
    }
    /**
     * @des
     * @param proxy 被代理的物件
     * @param method 被代理物件的方法
     * @param args 方法的引數
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("log:XXX在YYY時間開始列印...");
        Object result = method.invoke(target, args);
        System.out.println("log:XXX在MMM時間結束列印...");
        return result;
    }
}


/**
 * @Author: dong
 * @Project: DesignPatterns
 * @Description:
 * @Date: Created in 下午11:45 2018/7/21
 * @Modified By:
 */
public class TestJDKProxy {
    public static void main(String[] args) {
        PrintReal printReal = new PrintReal();
        ProxyPrint proxyPrint = new ProxyPrint(printReal);
        ClassLoader classLoader = printReal.getClass().getClassLoader();
        Print print = (Print) Proxy.newProxyInstance(classLoader, printReal.getClass().getInterfaces(), proxyPrint);
        print.print();
    }
}

相關推薦

【java項目實戰】代理模式Proxy Pattern,靜態代理 VS 動態代理

自己 text 好的 trace use 代理 分類 plproxy this 這篇博文,我們主要以類圖和代碼的形式來對照學習一下靜態代理和動態代理。重點解析各自的優缺點。 定義 代理模式(Proxy Pattern)是對象的結構型模式,代理模

設計模式之 - 代理模式Proxy Pattern

ride proxy idt object catch 實例化 圖片 null 人在 代理模式:代理是一種常用的設計模式,其目的就是為其他對象提供一個代理以控制對某個對象的訪問。代理類負責為委托類預處理消息,過濾消息並轉發消息,以及進行消息被委托類執行後的後續處理。很多可以

設計模式學習——代理模式Proxy Pattern

pre .cn mar str ubuntu 技術 運行 obj proxy 放假啦~學生們要買車票回家了,有汽車票、火車票,等。但是,車站很遠,又要考試,怎麽辦呢?找代理買啊,雖然要多花點錢,但是,說不定在搞活動,有折扣呢~ 1 /// 2 /// @fi

設計模式學習——代理模式Proxy Pattern之 強制代理強校驗,防繞過

arr cnblogs 其他 測試 auth using color ref use 上周溫習了代理模式:http://www.cnblogs.com/chinxi/p/7354779.html 在此進行拓展,學習強制代理。但是發現網上大多例子都有個“天坑”(我是這麽認為的

C#設計模式之十二代理模式Proxy Pattern【結構型】

ride col 安全 .html 使用權 防火墻 一對多 tro 橋接 原文:C#設計模式之十二代理模式(Proxy Pattern)【結構型】一、引言 今天我們要講【結構型】設計模式的第七個模式,也是“結構型”設計模式中的最後一個模式,該模式是【代理模式】,英文名稱

C#設計模式(13)——代理模式Proxy Pattern

web服務 軟件開發過程 smart stat args 橋接模式 復雜 src 空間 一、引言 在軟件開發過程中,有些對象有時候會由於網絡或其他的障礙,以至於不能夠或者不能直接訪問到這些對象,如果直接訪問對象給系統帶來不必要的復雜性,這時候可以在客戶端和目標對象之間增加一

重走Java設計模式——代理模式Proxy Pattern

代理模式 定義 為其他物件提供一種代理以控制對這個物件的訪問。 程式碼示例 我們將建立一個Image 介面和實現了 Image 介面的實體類。ProxyImage 是一個代理類,減少 RealImage 物件載入的記憶體佔用。 ProxyPatternDem

28.代理模式proxy pattern

1.結構 2.代理的種類(根據用途分類) 3.代理的優缺點 4.代理模式的實現 靜態代理(針對每個真實主題需要人為建立一個代理類) jdk動態代理(實質是生成一個實現我們傳入的介面,並且繼承Proxy的類,優點:針對某種功能的代理只需要實現一個InvocationHandler,然後

代理模式Proxy Pattern:簡單&粗暴解析

1.前言 在之前的文章設計模式(Design pattern):簡單&粗暴解析中已經為大家深入淺出解析了 設計模式 的 七大原則、三大型別。 本文為大家解析三大型別中 結構型 裡其中的 代理模式。 文章中例項  linhaojian的Githu

38C#設計模式——代理模式Proxy Pattern

引言 在軟體開發過程中,有些物件有時候會由於網路或其他障礙,以至於不能夠或者不能直接訪問到這些物件,如果直接訪問物件給系統帶來不必要的複雜性,這時候可以在客戶端和目標物件之間增加一層中間層,讓代理物件代替目標物件,然後客戶端只需要訪問代理物件,由代理物件去幫我們請求目標物件

設計模式代理模式Proxy Pattern

應用場景 Proxy代理模式是一種結構型設計模式,主要解決的問題是:直接訪問物件時帶來的問題。 為了保持行為的一致性,代理類和委託類通常會實現相同的介面,所以在訪問者看來兩者並無區別。 代理類種類: 靜態:建立代理類再對其編譯,在程式執行前代理類的.class檔案就已

代理模式 Proxy Pattern

切入故事: 我是遊戲至尊 定義: Provide a surrogate or placeholder for another object to control access to it.(為其他物件提供一種代理以控制對這個物件的訪問。 ) 通用類圖:       

代理模式Proxy Pattern:簡單&粗暴解析

1.前言 2.目錄 3.含義 一個類代表另一個類的功能。 4.解決 1.目標物件與訪問者高度耦合 & 難擴充套件的問題。 5.原理 **通過 【代理】這個中介,把 ”目標物件功能“ 與 ”訪問者“ 分離 **。 5.1 代理模式

代理模式Proxy Pattern

簡述 代理模式是一種結構型設計模式,代理模式主要包含三種角色:抽象物件角色、目標物件角色、代理物件角色,代理模式主要通過抽象物件角色來為目標物件提供一個代理物件,並由代理物件控制對原物件的引用,提供了一種對目標物件另外的訪問方式,這樣做的好處是,可以在目標物件

代理模式Proxy Pattern- 最易懂的設計模式解析

前言 今天我來全面總結一下Android開發中最常用的設計模式 - 代理模式。 目錄 1. 介紹 1.1 定義 給目標物件提供一個代理物件,並由代理物件控制對目標物件的引用 代理物件:起到中介作用,

設計模式代理模式 Proxy Pattern

        代理模式:代理接活,被代理人幹活。主要是用了java的多型特性,定義一個藉口, 讓代理類和被代理類都實現該介面,關鍵在於在代理類的構造方法中引用被代理類 的構造方法。 介面: public interface Start {     public void sing();     public

設計模式 —— 代理模式Proxy Pattern

代理模式(Proxy Pattern) 概念: 定義:代理模式 為另一個物件提供一個替身或佔位符以控制這個物件的訪問。 代理模式很好理解,在生活中也很常見。舉個簡單的例子,我們自己能做很多事情(動作),比如寫作業,出去玩等。當我們和父母在家的時候,

設計模式-代理模式Proxy Pattern學習總結

1.3.Cglib代理上面的靜態代理和動態代理模式都是要求目標物件是實現一個介面的目標物件,但是有時候目標物件只是一個單獨的物件,並沒有實現任何的介面,這個時候就可以使用以目標物件子類的方式類實現代理,這種方法就叫做:Cglib代理Cglib代理,也叫作子類代理,它是在記憶體中構建一個子類物件從而實現對目標物

代理模式Proxy Pattern

定義: 為其他物件一種代理以控制對這個物件的訪問。 代理模式也叫作委託模式,它是一項基本設計技巧,許多其他模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了委託模式,而且在日常的應用中,代理模式提供非常好的訪問控制。在一些著名的開元然間中也經常見到他的身影

設計模式代理模式Proxy Pattern

一、類圖 二、模式定義 代理模式: 給某一個物件提供一個代理或佔位符,並由代理物件來控制對原物件的訪問。 三、模式角色 (1) Subject(抽象主題角色): 它聲明瞭真實主題和代理主題的共同介面,這樣一來在任何使用真實主題的地方都可以使用代理主題,客戶端通