1. 程式人生 > >代理模式(Proxy)

代理模式(Proxy)

提高 時間 創建 -c 所表 文件 return int embed

1、概念

代理模式為其他對象提供一個代理以控制對這個對象的訪問,屬於結構性模式。從代碼的角度來分,代理可以分為兩種:一種是靜態代理,另一種是動態代理。
靜態代理就是在程序運行前就已經存在代理類的字節碼文件,代理類和委托類的關系在運行前就確定了。
動態代理類的源碼是在程序運行期間根據反射等機制動態的生成,所以不存在代理類的字節碼文件。代理類和委托類的關系是在程序運行時確定。

2、模式結構

  • Subject(抽象主題類):接口或者抽象類,聲明真實主題與代理的共同接口方法。
  • RealSubject(真實主題類):也叫做被代理類或被委托類,定義了代理所表示的真實對象,負責具體業務邏輯的執行,客戶端可以通過代理類間接的調用真實主題類的方法。
  • Proxy(代理類):也叫委托類,持有對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行。

3、使用場景

  • 當一個對象不能或者不想直接訪問另一個對象時,可以通過一個代理對象來間接訪問
  • 被訪問的對象不想暴露全部內容時,可以通過代理去掉不想被訪問的內容
  • 一個消耗資源較少的對象來代表一個消耗資源較多的對象,從而降低系統開銷、縮短運行時間時

4、優缺點

優點:

  • 協調調用者和被調用者,降低了系統的耦合度
  • 代理對象作為客戶端和目標對象之間的中介,起到了保護目標對象的作用
  • 以一個小對象代理一個大對象,達到優化系統提高運行速度的目的

缺點:

  • 調用者和真實主題之間增加了代理對象,因此可能會造成請求的處理速度變慢。
  • 實現代理模式需要額外的工作,從而增加了系統實現的復雜度

5、實例

靜態實例

public interface IUserDao {
    int save();
}
public class UserDao implements IUserDao {

    @Override
    public int save() {
        return 0;
    }
}
public class UserDaoProxy implements IUserDao {

    //接收保存目標對象
    private IUserDao target;

    public UserDaoProxy(IUserDao target) {
        this.target = target;
    }

    @Override
    public int save() {
        return target.save();
    }
}

動態實例:

還是使用靜態代理的IUserDao和UserDao 類,改造UserDaoProxy 類,利用java的newProxyInstance動態生成實例。

public class UserDaoProxy {

    //維護一個目標對象
    private Object target;

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

    //給目標對象生成代理對象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //運用反射執行目標對象方法
                        Object returnValue = method.invoke(target, args);
                        return returnValue;
                    }
                }
        );
    }
}
public static void main(String[] args) {
    // 目標對象
    IUserDao target = new UserDao();
    System.out.println(target.getClass());
    // 給目標對象,創建代理對象
    IUserDao proxy = (IUserDao) new UserDaoProxy(target).getProxyInstance();
    proxy.save();
}

代理模式(Proxy)