代理模式--靜態代理與動態代理 - 的區別聯繫

Proxy代理模式是什麼?
Proxy代理模式是一種結構型設計模式,主要解決的問題是:在直接訪問對象時帶來的問題
代理是一種常用的設計模式,其目的就是爲其他對象提供一個代理以控制對某個對象的訪問。代理類負責爲委託類預處理消息,過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。

使用場合
如果需要委託類處理某一業務,那麼我們就可以先在代理類中統一處理然後在調用具體實現類

代理模式分類
靜態代理:由程序員創建代理類或特定工具自動生成源代碼再對其編譯。在程序運行前代理類的.class文件就已經存在了。
動態代理:在程序運行時運用反射機制動態創建而成。

靜態代理

定義接口:

public interface HelloWord {
     void print();
}

定義實現類:

public class HelloWordImp1 implements HelloWord {
    @Override
    public void print() {
        System.out.println("hello world");
    }
}

定義代理實現類:

public class StaticProxy implements HelloWord {
    public HelloWord helloWord;
    public StaticProxy (HelloWord helloWord){
        this.helloWord = helloWord;
    }

    @Override
    public void print() {
        System.out.println("Welcome");
        helloWord.print();
    }
}

測試類:

public class TeststaticProxy {
    public static void main(String[] args) {
        HelloWord helloWord = new HelloWordImp1();
        StaticProxy staticProxy = new StaticProxy(helloWord);
        staticProxy.print();
    }
}

優點:
代理使客戶端不需要知道實現類是什麼,怎麼做的,而客戶端只需知道代理即可(解耦合)
缺點:
1)代理類和委託類實現了相同的接口,代理類通過委託類實現了相同的方法。這樣就出現了大量的代碼重複。如果接口增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的複雜度。
2)代理對象只服務於一種類型的對象,如果要服務多類型的對象。勢必要爲每一種對象都進行代理,靜態代理在程序規模稍大時就無法勝任了。

舉例說明:

代理可以對實現類進行統一的管理,如在調用具體實現類之前,需要打印日誌等信息,這樣我們只需要添加一個代理類,在代理類中添加打印日誌的功能,然後調用實現類,這樣就避免了修改具體實現類。滿足我們所說的開閉原則。但是如果想讓每個實現類都添加打印日誌的功能的話,就需要添加多個代理類,以及代理類中各個方法都需要添加打印日誌功能(如上的代理方法中刪除,修改,以及查詢都需要添加上打印日誌的功能)
即靜態代理類只能爲特定的接口(Service)服務。如想要爲多個接口服務則需要建立很多個代理類。代碼複用率低,這時候就需要用到動態代理。

動態代理:

定義接口:

public interface Iuser {
    void eat(String s);
}

定義實現類:

public class UserImpl implements Iuser{

    @Override
    public void eat(String s) {
        System.out.println("我要吃"+s);
    }
}

定義代理類:

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

public class InvocationHandlerproxy implements InvocationHandler {
    private Object object;
    public InvocationHandlerproxy(Object obj){

        this.object = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置內容");
        method.invoke(object,args);
        System.out.println("後置內容");
        return null;
    }
}

測試類:

import java.lang.reflect.Proxy;


public class ProxyTest {
    public static void main(String[] args) {
        Iuser iuser = new UserImpl();
        InvocationHandlerproxy h = new InvocationHandlerproxy(iuser);
        Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(),new Class[]{Iuser.class},h);

        proxy.eat("蘋果");
    }
}

爲了通過一個代理類完成全部的代理功能,那麼我們就需要用動態代理

靜態代理,一個代理只能代理一種類型,而且是在編譯器就已經確定被代理的對象。而動態代理是在運行時,通過反射機制實現動態代理,並且能夠代理各種類型的對象

在Java中要想實現動態代理機制,需要java.lang.reflect.InvocationHandler接口
和 java.lang.reflect.Proxy 類的支持

動態代理的優點:

動態代理與靜態代理相比較,最大的好處是接口中聲明的所有方法都被轉移到調用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在接口方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。而且動態代理的應用使我們的類職責更加單一,複用性更強,動態代理也是一種AOP(面向切面編程)思想的實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章