【設計模式】代理模式

胖達利亞發表於2021-10-17

這就是一個代理模式,讓王工改需求,需要聯絡李總,李總再把工作安排給王工,最終完成了同樣的目的,但是有個了中間人。

 

同樣在Java裡的代理模式,也這個道理,客戶端不直接訪問實際的物件,而是通過中間的代理物件來訪問實際物件。

代理模式分為靜態代理和動態代理

 

靜態代理

代理和被代理物件在代理之前是確定的。都實現了相同的介面或繼承相同的抽象類。舉例:

建立IUser介面

/**
 * 使用者介面
 */
public interface IUser {

    void login();
} 

目標物件User:

/**
 * 實現使用者登入,目標物件
 */
public class User implements IUser {
    @Override
    public void login() {
        System.out.println("使用者登入中.....");
    }
}

代理物件UserProxy

/**
 * 代理物件
 */
public class UserProxy implements IUser {

    private IUser target;

    public UserProxy(IUser target) {
        this.target = target;
    }

    @Override
    public void login() {
        System.out.println("使用者開始登入");
        target.login();
        System.out.println("使用者結束登入");
    }
}
 

 

測試Run.java

/**
 * 測試類
 */
public class Run {
    public static void main(String[] args) {

        //目標物件
        User target = new User();

        //代理物件,同時把目標物件傳給代理物件
        UserProxy userProxy = new UserProxy(target);
        userProxy.login();

    }
}

執行結果:

使用者開始登入
使用者登入中.....
使用者結束登入

 

總結:

1.靜態代理可以代理實現任意介面的目標物件,通用性強。

2.介面有修改,目標物件和代理物件都要進行修改,增加了維護難度。

3.代理物件對應著一個目標物件,每個目標物件實現了部分介面,如果目標物件很多,那麼靜態代理物件也變得臃腫起來。

為了解決2,3問題,引入動態代理。

 

動態代理

這裡介紹使用JDK的代理方式,同樣可以代理實現介面的類。

步驟如下:

1.編寫一個目標類的介面。

2.實現介面的目標類。

3.建立一個動態代理類,實現InvocationHandler介面,重寫invoke方法。

舉例:步驟1,2使用靜態代理的IUser介面和User目標類。

建立一個動態代理類:

/**
 * 動態代理類
 */
public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    /**
     * proxy    被代理的物件
     * method   被代理物件的方法
     * args     方法的引數
     * return   Object方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("開始登入");
        //執行目標類方法
        Object result = method.invoke(target, args);
        System.out.println("結束登入");
        return result;
    }
}
 

 

測試類:Run2.java

/**
 * 測試類
 */
public class Run2 {

    public static void main(String[] args) {

        //目標物件
        User target = new User();

        //代理物件,同時把目標物件傳給代理物件
        DynamicProxy dynamicProxy = new DynamicProxy(target);

        //給目標生產代理物件
        /**
         * loader      類載入器
         * interfaces  實現介面
         * h           InvocationHandle
         */
        IUser iUser = (IUser) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), dynamicProxy);
        iUser.login();
    }
}

執行結果:

使用者開始登入
使用者登入中.....
使用者結束登入

相關文章