1. 程式人生 > 實用技巧 >代理模式學習

代理模式學習

代理模式

代理模式是結構型模式,相當於給一個物件生成一個代理物件,我們去訪問的時候直接面對的是代理物件。在平時的生活中也有類似的例子,比如房產中介,我們在租房的時候面對的不是真正的房東而是中介,這個中介就相當於房東的代理物件。代理物件可以對原物件的功能進行增強。下面通過一張圖來展示下代理模式。

在上圖中,我們可以看到代理類和被代理類都需要繼承同一個介面,然後代理類又繼承了被代理類,這樣就可以對被代理類進行功能增強。然後我們使用者訪問的是代理類。

代理型別的分類:

  • 靜態代理
  • 動態代理

靜態代理

靜態代理:相當於提前實現好代理類,在需要的時候直接建立例項即可。靜態代理存在一些侷限,比如一些被代理類需要相同的功能增強邏輯,靜態代理就需要一個個去實現這些類的代理類,非常的麻煩,編碼量大,同時也不易管理。

靜態代理程式碼實現

場景描述:使用者去租房,租房找的都是中介而並非房東

  1. 實現租房介面
//租房介面
public interface Rent {
    void rentHouse();
}
  1. 房東類的實現(也就是被代理類),需要實現介面
//房東類實現了租房的介面
public class Host implements Rent {
    @Override
    public void rentHouse() { 
        System.out.println("我是房東,我要出租房子");
    } 
}
  1. 中介類的實現(也就是代理類),需要實現介面
//中介類,同樣實現了租房介面,並且需要加入房東類,呼叫房東類中的功能
public class RentProxy implements Rent {
    private Host host;
    public RentProxy(Host host) {
        this.host = host;
    }
    @Override
    public void rentHouse() { 
        System.out.println("我是中介,帶著客戶去看房子"); host.rentHouse();
    } 
}
  1. 測試程式碼
public class ProxyTest {
    public static void main(String[] args) {
        //呼叫中介的租房方法
        RentProxy proxy = new RentProxy(new Host()); 
        proxy.rentHouse();
    }
}

動態代理

動態代理,相對於靜態代理來說就是代理類是動態生成的而不是提前編碼好。動態代理,減少了編碼量以及方便管理。這裡動態代理的實現是基於介面的實現。動態代理的有兩種常見的實現:

  • Jdk動態代理:基於介面的實現。
  • cglib動態代理:基於類的實現。

下面的程式碼實現是基於介面的實現,也就是jdk動態代理

動態代理程式碼實現

  1. 同靜態代理第一步:實現租房介面
  2. 同靜態代理第二步:實現房東類
  3. 實現代理handler,這裡沒有實現代理類,區別於靜態代理
//實現代理handler
public class RentProxyHandler implements InvocationHandler {
    private Object rent;
    public RentProxyHandler(Object rent) {
        this.rent = rent;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws
            Throwable {
        //功能增強
        System.out.println("中介帶著客戶去看房子"); 
        //呼叫被代理類中的方法
        method.invoke(rent,args);
        return null;
    } 
}
  1. 測試程式碼
public class ProxyTest {
    public static void main(String[] args) {
        //建立需要被代理的物件,這裡就是房東
        Host host = new Host();
        //建立代理handller,然後將需要被代理的物件傳入到handller中
        RentProxyHandler proxyHandler = new RentProxyHandler(host);
        //這裡用於動態的生成代理物件,也就是相當於我們之前寫RentProxy,不過這裡我們是自動生成的
        Rent rentProxy = (Rent) Proxy.newProxyInstance(host.getClass().getClassLoader(),
                        host.getClass().getInterfaces(), proxyHandler);
        rentProxy.rentHouse();
    }
}