代理是一種常用的設計模式,其目的就是爲其他對象提供一個代理以控制對某個對象的訪問。代理類負責爲委託類預處理消息,過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。
爲了保持行爲的一致性,代理類和委託類通常會實現相同的接口,所以在訪問者看來兩者沒有絲毫的區別。通過代理類這中間一層,能有效控制對委託類對象的直接訪問,也可以很好地隱藏和保護委託類對象,同時也爲實施不同控制策略預留了空間,從而在設計上獲得了更大的靈活性。Java動態代理機制以巧妙的方式近乎完美地實踐了代理模式的設計理念。
按照代理類的創建時期,代理類可分爲兩種。
靜態代理類:
由程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。靜態代理原理就是聚合+多態。
代理模式一般涉及到的角色有:
抽象角色:聲明真實對象和代理對象的共同接口;
代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當於對真實對象進行封裝。
真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。
//抽象角色:
abstract public class Subject{
abstract public void request();
}
//真實角色:實現了Subject的request()方法。
public class RealSubject extends Subject{
public RealSubject(){
}
public void request(){
System.out.println("From real subject.");
}
}
//代理角色:
public class ProxySubject extends Subject{
private RealSubject realSubject; //以真實角色作爲代理角色的屬性
public ProxySubject(){
}
public void request(){ //該方法封裝了真實對象的request方法
preRequest();
if( realSubject == null ){
realSubject = new RealSubject();
}
realSubject.request(); //此處執行真實對象的request方法
postRequest();
}
private void preRequest(){
//something you want to do before requesting
}
private void postRequest(){
//something you want to do after requesting
}
}
//客戶端調用:
public class Client{
public static void main(String args[]){
Subject sub=new ProxySubject();
Sub.request();
}
}
由以上代碼可以看出,客戶實際需要調用的是RealSubject類的request()方法,現在用ProxySubject來代理RealSubject類,同樣達到目的,同時還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。
但是靜態代理存在一個問題:如果要按照上述的方法使用代理模式,那麼真實角色必須是事先已經存在的,並將其作爲代理對象的內部屬性。但是實際使用時,一個真實角色必須對應一個代理角色,如果大量使用會導致類的急劇膨脹,重複的代碼會出現很多,這是一個很嚴重的問題;此外,如果事先並不知道真實角色,怎麼使用代理那?
怎麼解決這兩個問題那??這就需要動態代理來解決了。