代理意思就是說有人幫你做一件事情。舉個例子,現在有一份文件想要領導簽字,但是領導不是隨便就能見的,那麼,就只得先去找領導的祕書,告訴祕書想要找領導簽字,然後祕書會代替你去找領導簽字,然後將簽好字的文件還給你。這麼做有兩個原因,第一個,領導不是隨便就能調用的,在這個例子裏面,領導的簽字功能只有祕書可以調用,當客戶端調用領導簽字這個功能的時候,祕書會把這個調用截獲了,再通過自己去調用領導簽字;第二個,有些字可以籤,有些字簽了是要出問題的,那麼什麼可以籤什麼不可以籤,祕書會進行判斷,祕書會把能籤的給領導,不能籤的直接返回給客戶並告訴他籤不了。講完了上面的例子,回到JAVA的設計上來,使用代理的兩個原因,一,是有些類不能被直接調用,例如它在另一臺機器上,調用的話需要處理網絡,編碼解碼等繁雜的但是跟業務邏輯無關的操作,如果客戶端不用代理直接調用就會寫很多跟業務邏輯無關的代碼,這個和JAVA設計中的功能單一性原則相違背,因爲一旦這個類的位置換了,那麼客戶端就得改,那麼就有可能會影響到業務邏輯,所以這麼做是不行的;第二,有可能這個類某些用戶可以訪問,某些用戶沒權限訪問,那麼如果不使用代理,那麼這個被調用的類不僅要實現自己的功能,還要自己來實現權限判斷的功能,這明顯違背了降低耦合性的原則,於是,就有了代理。
JAVA裏面,代理分爲了兩種,一種是靜態的,沒有用到JDK提供的用於代理模式的類,另一種是動態代理,它用到了JDK裏的一些類。
先來看看靜態的,靜態的很容易理解:
- abstract class Subject {
- abstract public void request();
- }
- // 真實角色:實現了Subject的request()方法。
- class RealSubject extends Subject {
- public RealSubject() {
- }
- public void request() {
- System.out.println( " From real subject. " );
- }
- }
- // 代理角色:
- 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 Test{
- public static void main(String args[]){
- // 客戶端調用:
- Subject sub = new ProxySubject();
- sub.request();
- }
- }
上面這段代碼中,代理類繼承了被代理的類,然後去重載了他的方法,在調用的時候,直接new一個代理類的對象作爲被代理類的對象,這樣就達到了代理的目的。
另外一個是動態代理,來看一段代碼:
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Method;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Proxy;
- interface Subject{
- public void request();
- }
- //具體角色RealSubject:實現了Subject接口的request()方法。
- class RealSubject implements Subject{
- public RealSubject(){
- }
- public void request(){
- System.out.println("From real subject.");
- }
- }
- //代理角色:
- class DynamicSubject implements InvocationHandler{
- private Object sub;
- public DynamicSubject(Object sub){
- this.sub = sub;
- }
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("before calling " + method);
- method.invoke(sub,args);
- System.out.println("after calling " + method);
- return null;
- }
- }
- public class Test{
- @SuppressWarnings("rawtypes")
- static public void main(String[] args) throws Throwable{
- RealSubject rs = new RealSubject(); //在這裏指定被代理類
- InvocationHandler ds = new DynamicSubject(rs); //初始化代理類
- Class cls = rs.getClass();
- //以下是分解步驟
- Class<?> c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces());
- Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});
- Subject subject1 =(Subject) ct.newInstance(new Object[]{ds});
- subject1.request();
- //以下是一次性生成
- Subject subject2 = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ds);
- subject2.request();
- }
- }
上面的代碼沒有多少需要解釋的,照着用就行了,但是我還是想說一句,subject1.request()和subject2.request()這兩句話,雖然看似簡單的調用(因爲subject1和subject2都是Subject的對象),實際上,這兩個調用已經被DynamicSubject截獲了,這裏截獲這個詞很能表達代理的意思,理解了截獲這個詞,就能理解Proxy模式了。