java的兩種代理模式

代理模式是什麼

代理模式是一種設計模式,簡單說即是在不改變源碼的情況下,實現對目標對象功能擴展

比如有個歌星對象叫RealStar,他十分會唱歌,但是這個歌手十分忙,他只想唱歌不願意做其他的事情,因此你需要幫助他完成任務!

Star接口

package com.Geeksun.proxy.dynamicProxy;

public interface Star {
    void sign();
    
    void payMoney();
    
    void sing();
}

RealStar

package com.Geeksun.proxy.dynamicProxy;

public class RealStar implements Star {
    @Override
    public void sign() {
        System.out.println("我不會!");
    }

    @Override
    public void payMoney() {
        System.out.println("我不會!");
    }

    @Override
    public void sing() {
        System.out.println("sing");
    }
}

1.靜態代理

這時候有一個代理對象

package com.Geeksun.proxy.staticProxy;

public class ProxyStar implements Star{

    private Star star;

    public ProxyStar(Star star){
        this.star = star;
    }

    @Override
    public void sign() {
        System.out.println("sign");
    }

    @Override
    public void payMoney() {
        System.out.println("payMoney");
    }

    @Override
    public void sing() {
        star.sing();
    }
}

 

 總結:其實這裏做的事情無非就是,創建一個代理類ProxyStar,繼承了Star接口並實現了其中的方法。只不過這種實現特意包含了目標對象的方法,正是這種特徵使得看起來像是“擴展”了目標對象的方法。假使代理對象中只是簡單地對sing方法做了另一種實現而沒有包含目標對象的方法,也就不能算作代理模式了。所以這裏的包含是關鍵。

  缺點:這種實現方式很直觀也很簡單,但其缺點是代理對象必須提前寫出,如果接口層發生了變化,代理對象的代碼也要進行維護。如果能在運行時動態地寫出代理對象,不但減少了一大批代理類的代碼,也少了不斷維護的煩惱,不過運行時的效率必定受到影響。這種方式就是接下來的動態代理。

2.動態代理(也叫JDK代理)

 跟靜態代理的前提一樣,依然是對Star對象進行擴展

StarHandler

package com.Geeksun.proxy.dynamicProxy;

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

public class StarHandler implements InvocationHandler {
    private Star star;

    public StarHandler(Star star){
        this.star = star;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = null;
        System.out.println("訂票");
        if(method.getName().equals("sing")){
            object = method.invoke(star,args);
        }
        System.out.println("收錢");
        return object;
    }
}

Client

package com.Geeksun.proxy.dynamicProxy;

import java.lang.reflect.Proxy;

public class Client {

    public static void main(String[] args) {
        StarHandler starHandler = new StarHandler(new RealStar());

        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class},starHandler);
        proxy.sign();
        proxy.sing();
    }

}

調用Proxy類的靜態方法newProxyInstance即可,該方法會返回代理類對象

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

接收的三個參數依次爲:

  • ClassLoader loader:指定當前目標對象使用類加載器,寫法固定
  • Class<?>[] interfaces:目標對象實現的接口的類型,寫法固定
  • InvocationHandler h:事件處理接口,需傳入一個實現類,一般直接使用匿名內部類
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章