代理模式(Proxy)


 一、代理模式介紹

代理模式:為其他對象提供一種代理以便控制對這個對象的訪問。

可以詳細控制訪問某個類(對象)的方法,在調用這個方法前作的前置處理(統一的流程代碼放到代理中處理)。調用這個方法后做后置處理。

例如:明星的經紀人,租房的中介等等都是代理

代理模式分類:

1.靜態代理(靜態定義代理類,我們自己靜態定義的代理類。比如我們自己定義一個明星的經紀人類)

2.動態代理(通過程序動態生成代理類,該代理類不是我們自己定義的。而是由程序自動生成)比較重要!!

        JDK自帶的動態代理

        javaassist字節碼操作庫實現

        CGLIB

        ASM(底層使用指令,可維護性較差)

靜態代理模式結構圖:

靜態代理模式一般會有三個角色:

抽象角色:指代理角色(經紀人)和真實角色(明星)對外提供的公共方法,一般為一個接口

真實角色:需要實現抽象角色接口,定義了真實角色所要實現的業務邏輯,以便供代理角色調用。也就是真正的業務邏輯在此。

代理角色:需要實現抽象角色接口,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。

                  將統一的流程控制都放到代理角色中處理!

 

二、代理模式代碼實現

2.1 靜態代理模式

這里定義一個抽象角色接口(Star)、代理角色實現(ProxyStar)、真實角色實現(RealStar)

抽象角色接口:提供了與明星合作的一系列流程

1
2
3
4
5
6
7
8
9
10
11
12
package com.fz.proxy.staticProxy;
 
/**
  * 抽象角色:提供代理角色和真實角色對外提供的公共方法
  */
public interface Star {
     void confer(); //面談
     void signContract(); //簽合同
     void bookTicket(); //訂票
     void sing(); //唱歌
     void collectMoney(); //收尾款
}

代理角色實現類:代理角色中代理了真實角色所需要的操作(唱歌)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.fz.proxy.staticProxy;
  
/**
  * 代理角色(明星經紀人):
  */
public class ProxyStar implements Star{
     private Star star; //真實對象的引用(明星)
     @Override
     public void confer() {
         System.out.println( "ProxyStar.confer()" );
     }
     @Override
     public void signContract() {
         System.out.println( "ProxyStar.signContract()" );
     }
     @Override
     public void bookTicket() {
         System.out.println( "ProxyStar.bookTicket()" );
     }
     @Override
     public void sing() {
         star.sing(); //真實對象的操作(明星唱歌)
     }
     @Override
     public void collectMoney() {
         System.out.println( "ProxyStar.collectMoney()" );
     }
     public ProxyStar(Star star) { //通過構造器給真實角色賦值
         this .star = star;
     }
}

真實角色實現類:這里的真實角色中其實只做了一個唱歌的操作,這是真實角色真正的業務邏輯部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.fz.proxy.staticProxy;
 
/**
  * 真實角色(明星藝人):
  */
public class RealStar implements Star{
     @Override
     public void confer() {
         System.out.println( "RealStar.confer()" );
     }
     @Override
     public void signContract() {
         System.out.println( "RealStar.signContract()" );
     }
     @Override
     public void bookTicket() {
         System.out.println( "RealStar.bookTicket()" );
     }
     @Override
     public void sing() {
         System.out.println( "張學友.sing()" ); //真實角色的操作:真正的業務邏輯
     }
     @Override
     public void collectMoney() {
         System.out.println( "RealStar.collectMoney()" );
     }
}

測試代理類:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
     Star real = new RealStar();
     Star proxy = new ProxyStar(real);
     proxy.confer();
     proxy.signContract();
     proxy.bookTicket();
     proxy.sing(); //真實對象的操作(明星唱歌)
     proxy.collectMoney();
}

輸出結果為:

        ProxyStar.confer()

        ProxyStar.signContract()

        ProxyStar.bookTicket()

        張學友.sing()     //這里是真實角色的業務邏輯處理

        ProxyStar.collectMoney()

以上代碼UML圖如下:

2.2 動態代理代碼實現

動態代理是不需要定義代理角色的,通過一個處理器來處理代理角色的業務邏輯。

抽象角色接口:提供了與明星合作的一系列流程

1
2
3
4
5
6
7
8
9
10
11
12
package  com.fz.proxy.staticProxy;
 
/**
  * 抽象角色:提供代理角色和真實角色對外提供的公共方法
  */
public  interface  Star {
     void  confer(); //面談
     void  signContract(); //簽合同
     void  bookTicket(); //訂票
     void  sing(); //唱歌
     void  collectMoney(); //收尾款
}
 

真實角色實現類:這里的真實角色中其實只做了一個唱歌的操作,這是真實角色真正的業務邏輯部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package  com.fz.proxy.staticProxy;
 
/**
  * 真實角色(明星藝人):
  */
public  class  RealStar  implements  Star{
     @Override
     public  void  confer() {
         System.out.println( "RealStar.confer()" );
     }
     @Override
     public  void  signContract() {
         System.out.println( "RealStar.signContract()" );
     }
     @Override
     public  void  bookTicket() {
         System.out.println( "RealStar.bookTicket()" );
     }
     @Override
     public  void  sing() {
         System.out.println( "張學友.sing()" ); //真實角色的操作:真正的業務邏輯
     }
     @Override
     public  void  collectMoney() {
         System.out.println( "RealStar.collectMoney()" );
     }
}
 

代理角色的處理器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.fz.proxy.dynamicProxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
/**
  * 處理器
  */
public class StarHandler implements InvocationHandler{
     private Star realStar; //真實角色
     /**
      * 所有的流程控制都在invoke方法中
      * proxy:代理類
      * method:正在調用的方法
      * args:方法的參數
      */
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         Object object = null ;
         System.out.println( "真實角色調用之前的處理....." );
         if (method.getName().equals( "sing" )) {
             object = method.invoke(realStar, args); //激活調用的方法   
         }
         System.out.println( "真實角色調用之后的處理....." );
         return object;
     }
     //通過構造器來初始化真實角色
     public StarHandler(Star realStar) {
         super ();
         this .realStar = realStar;
     }
}

測試代理模式:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
     //真實角色
     Star realStar = new RealStar();
     //處理器
     StarHandler handler = new StarHandler(realStar);
     //代理類
     Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star. class }, handler);
     proxy.sing(); //調用代理類的唱歌方法:其實調用的是真實角色的唱歌方法
}

 

 



Java23種設計模式學習筆記【目錄總貼】

參考資料:

  大話設計模式(帶目錄完整版).pdf

  HEAD_FIRST設計模式(中文版).pdf

  尚學堂_高淇_java300集最全視頻教程_【GOF23設計模式】




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM