代理設計模式

前言:

    網上有那麼多寫設計模式的博客爲什麼還要寫設計模式呢?因爲我不會,而且如果只是看看別人寫的往往自己理解的很淺,需通過自己寫一寫加深影響。

一、什麼是代理模式

    爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

二、代理模式的組成

 抽象角色:通過接口或抽象類聲明真實角色實現的業務方法。
 代理角色:實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。
 真實角色:實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色調用

三、模式結構

1、靜態代理

抽象角色:

public interface ProxyInf {
    int addUser(int num);
}

代理角色:

public class ProxyPerson implements ProxyInf {
    private final Administrator admin;
    public ProxyPerson (Administrator admin){
        this.admin = admin;
    }
    @Override
    public int addUser(int num) {
        return admin.addUser(num);
    }
}

真實角色:

public class Administrator implements ProxyInf{
    private int totalNum = 100 ;
    @Override
    public int addUser(int num) {
        return totalNum +num ;
    }
    public void deleteUser(int num){
        totalNum  -= num ;
    }
}

可以做到在不修改目標對象的功能前提下,對目標功能擴展.
缺點:因爲代理對象需要與目標對象實現一樣的接口,所以會有很多代理類,類太多.同時,一旦接口增加方法,目標對象與代理對象都要維護

2、動態代理
動態代理有別於靜態代理,是根據代理的對象,動態創建代理類。可以避免靜態代理中代理類接口過多的問題。動態代理是通過反射來實現的,藉助Java自帶的java.lang.reflect.Proxy,通過固定的規則生成。
動態代理的代碼和靜態差不多,區別在於代理角色。
代理角色:

public class ProxyPerson implements InvocationHandler {
    private final Object object;
    public ProxyPerson(Object object){
        this.object= object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(proxy, args);
        return result;
    }
}

調用:

ProxyInf  proxyInf= new Administrator();
ProxyPerson proxyPerson = new ProxyPerson(proxyInf);
ClassLoader classLoader = proxyInf.getClass().getClassLoader();
ProxyInf proxyInstance =
                (ProxyInf)Proxy.newProxyInstance(classLoader, new Class[]{ProxyInf.class}, proxyPerson);
proxyInstance.addUser();

Proxy類的靜態方法newProxyInstance()方法生成了一個對象,這個對象實現了數組中指定的接口。沒錯,返回值proxyInstance 是ProxyInf接口的實現類。你不要問這個類是哪個類,你只需要知道proxyInstance 是ProxyInf接口的實現類就可以了。

動態代理就是在運行時生成一個類,這個類會實現你指定的一組接口,而這個類沒有.java文件,是在運行時生成的,你也不用去關心它是什麼類型的,你只需要知道它實現了哪些接口即可。

Proxy類的newInstance()方法有三個參數:
  

  • ClassLoader loader:它是類加載器類型,你不用去理睬它,你只需要知道怎麼可以獲得它就可以了:MyInterface.class.getClassLoader()就可以獲取到ClassLoader對象,沒錯,只要你有一個Class對象就可以獲取到ClassLoader對象; 

  • Class[] interfaces:指定newProxyInstance()方法返回的對象要實現哪些接口,沒錯,可以指定多個接口,例如上面例子只我們只指定了一個接口:Class[] cs = {ProxyInf.class};  

  • InvocationHandler h:它是最重要的一個參數!它是一個接口!它的名字叫調用處理器!它只有一個方法,即invoke()方法!它是對代理對象所有方法的唯一實現。也就是說,無論你調用代理對象上的哪個方法,其實都是在調用InvocationHandler的invoke()方法。
      
    methd.invoke(proxy, args)方法,第一個參數需要把原來的具體實現類作爲參數傳遞進去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章