代理模式

什么是代理

這里的代理可以聯(lián)系生活中的代理,就是代表某些人或事物做一些事情,舉幾個例子:1.中介就是一個典型的代理,你把房子掛到中介,中介就會幫你把房子的標價報給想買房的人;2.你打官司的時候,花錢請了律師,律師就會幫你打官司,替你說話..等等現(xiàn)實中有很多代理的例子。

為什么使用代理

還是引用上面的例子,你之所以把房子掛到中介,是因為你很忙,沒時間處理,而且中介可以聯(lián)系更多的買家;請律師,是因為律師懂得更多的法律知識,相當于對你進行了武裝。

軟件應用中的代理

經(jīng)過上面對現(xiàn)實生活中代理的簡單介紹,下面說一下我們編寫軟件應用中代理模式的使用。
在軟件應用中,代理模式的使用有三種情況:靜態(tài)代理,JDK動態(tài)代理),cglib動態(tài)代理;下面進行分別的介紹。

  • 靜態(tài)代理
    靜態(tài)代理是指被代理類和代理類都實現(xiàn)同一個接口,對于被代理類的方法訪問需要通過代理類調用
  • 靜態(tài)代理的缺點:
    1、代理的職能單一,在代碼中需要寫多個代理來完成不同的功能
    2、在編譯器已經(jīng)確定對被代理類的方法的調用,不適合做更多的擴展

示例代碼:
首先是公用接口

/**
 * Created by bitsino-001 on 2019/5/17.
 * 通過房子中介演示靜態(tài)代理
 * 這是個買房者和中介的公用接口
 */
public interface SellHouse {
    void price_house();
}

被代理類實現(xiàn)公用接口,這里就是賣房子的人

/**
 * Created by bitsino-001 on 2019/5/17.
 * 實際賣方的人(被代理類)
 */
public class Seller implements SellHouse {
    @Override
    public void price_house() {
        System.out.println("我是房主,萬科洋房,110平,售價150萬!");
    }
}

接下來是代理類也實現(xiàn)公用接口,這里就是房屋中介

/**
 * Created by bitsino-001 on 2019/5/17.
 * 中介代理類
 */
public class Zhongjie implements SellHouse {
    //
    Seller seller = new Seller();

    @Override
    public void price_house() {
        System.out.println("我是房屋中介,房主急售!");
        seller.price_house();
    }
}

下面是測試代碼

/**
 * Created by bitsino-001 on 2019/5/17.
 */
public class TestProxy {
    public static void main(String[] args) {
        SellHouse sellHouse = new Zhongjie();
        sellHouse.price_house();
    }
}

輸出結果:通過代理類調用了被代理類的方法,同時,也可以看做代理類對被代理類做了宣傳,也可以叫做增強,這個概念在后面的學習中會看到,如果學習了spring ,對AOP有了解那么這個概念應該熟悉。


圖片.png
  • JDK動態(tài)代理
    JDK動態(tài)代理和靜態(tài)代理類似,需要實現(xiàn)公共的接口,但是彌補了上面說的靜態(tài)代理的缺點。動態(tài)代理是在運行時動態(tài)的為被代理類創(chuàng)建代理對象,公用接口中的方法都被轉移到調用處理器一個集中的方法中執(zhí)行,可以更加靈活的處理多個方法的調用執(zhí)行。

示例代碼:

package dynamic_proxy;

/**
 * Created by bitsino-001 on 2019/5/17.
 * 一個普通的用戶,需要請律師代理他打官司
 */
public class User implements DaGuanSi {
    @Override
    public void juzheng() {
        System.out.println("用戶請律師幫忙舉證");
    }

    @Override
    public void susong() {
        System.out.println("用戶請律師幫忙訴訟");
    }
}
package dynamic_proxy;

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

/**
 * Created by bitsino-001 on 2019/5/17.
 * 演示如何實現(xiàn)動態(tài)代理
 *
 */
public class TestDynamicProxy {
    public static void main(String[] args) {
        //獲得代理類,需要用到JDK中的 Proxy.newProxyInstance()方法
        // 在Proxy.newProxyInstance()中需要傳入三個參數(shù)
      /*  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
      *    第一個是被代理類的類加載器,第二個是被代理類實現(xiàn)的接口,第三個參數(shù)是用來動態(tài)調用方法的接口
      *    想必介紹到這里,熟悉java反射的朋友應該想到了,動態(tài)代理是通過反射來實現(xiàn)的運行時方法調用
      * */

        User user = new User();
          //獲得代理對象
        DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            @Override
          //當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律師");
                Object invoke = method.invoke(user,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
                System.out.println("本代理律師發(fā)言完畢");
                return invoke;
            }
        });

        proxy.juzheng();
        proxy.susong();



    }
}


為了演示動態(tài)代理的優(yōu)勢,我們再通過動態(tài)代理來為上面的賣房子的例子做一下實現(xiàn),這次我們只需要將動態(tài)代理中的代理對象聲名為Seller(賣房者),接口改成賣房子的公共接口,就會動態(tài)的生成代理對象,當調用代理對象的方法時,也會調用被代理對象的方法。

package dynamic_proxy;

import static_proxy.SellHouse;
import static_proxy.Seller;

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

/**
 * Created by bitsino-001 on 2019/5/17.
 * 演示如何實現(xiàn)動態(tài)代理
 *
 */
public class TestDynamicProxy {
    public static void main(String[] args) {
        //獲得代理類,需要用到JDK中的 Proxy.newProxyInstance()方法
        // 在Proxy.newProxyInstance()中需要傳入三個參數(shù)
      /*  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
      *    第一個是被代理類的類加載器,第二個是被代理類實現(xiàn)的接口,第三個參數(shù)是用來動態(tài)調用方法的接口
      *    想必介紹到這里,熟悉java反射的朋友應該想到了,動態(tài)代理是通過反射來實現(xiàn)的運行時方法調用
      * */

    /*    User user = new User();
        //獲得代理對象
        DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律師");
                Object invoke = method.invoke(user,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
                System.out.println("本代理律師發(fā)言完畢");
                return invoke;
            }
        });

        proxy.juzheng();
        proxy.susong();*/


        Seller seller = new Seller();
        //獲得代理對象
        SellHouse proxy = (SellHouse) Proxy.newProxyInstance(seller.getClass().getClassLoader(), seller.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //當通過代理對象調用xxx方法時就會調用下面的方法執(zhí)行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("各位好,我是代理律師");
                Object invoke = method.invoke(seller,args);//這里就是通過反射執(zhí)行代理類的方法,也就是間接的調用被代理類的方法
                System.out.println("本代理律師發(fā)言完畢");
                return invoke;
            }
        });

       proxy.price_house();



    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容