GOF23設計模式之代理模式(proxy)

1、代理模式概述

  一、代理模式的核心做用

    (1)經過代理,控制對象的訪問;java

    (2)能夠詳細的控制訪問某個(某類)對象的方法,在調用這個方法前作前置處理,調用這個方法後作後置處理。(AOP的微實現)編程

        代理模式是 AOP(Aspect Oriented Programming 面向切面編程)的核心實現機制。安全

  二、代理模式的核心角色

    (1)抽象角色框架

      定義代理角色和真實角色的公共對外方法。ide

    (2)真實角色性能

      實現抽象角色,定義真實角色所須要實現的業務邏輯,供代理角色調用。測試

      關注真正的業務邏輯。this

    (3)代理角色spa

      實現抽象角色,是真實角色的代理,經過真實角色的業務邏輯輔方法來實現抽象方法,並附加本身的操做。代理

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

  三、代理模式的使用場景

    (1)安全代理: 屏蔽對真實角色的訪問;

    (2)經過代理類處理遠程方法調用(RMI Remote Method Invocation 遠程方法調用);

    (3)延遲加載:先加載輕量級的代理對象,真正須要再加載真實對象。

  四、代理模式的分類

    (1)靜態代理(靜態定義代理類)

    (2)動態代理(動態生成代理類)

      ① JDK自帶的動態代理

      ② javassist字節碼操做庫實現

      ③ CGLIB

        CGLIB是一個功能強大,高性能的代碼生成包。它爲沒有實現接口的類提供代理,爲JDK的動態代理提供了很好的補充。

        一般可使用Java的動態代理建立代理,但當要代理的類沒有實現接口或者爲了更好的性能,CGLIB是一個好的選擇。

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

        ASM是一個java字節碼操縱框架,它能被用來動態生成類或者加強既有類的功能。

2、代理模式之靜態代理

  示例代碼場景:周杰倫開演唱會時,面談、籤合同、訂票等操做都是由周杰倫的經紀人來完成,唱歌部分由他本人完成,最後收款也是由經紀人來完成。

  (1)建立抽象角色

 1 /**
 2  * 抽象角色
 3  * @author CL
 4  *
 5  */
 6 public interface Star {
 7     /**
 8      * 面談 
 9      */
10     void confer();
11     /**
12      * 籤合同
13      */
14     void signConstract();
15     /**
16      * 訂票
17      */
18     void bookTicket();
19     /**
20      * 唱歌
21      */
22     void sing();
23     /**
24      * 收款
25      */
26     void collectMoney();
27 }

  (2)定義真實角色

 1 /**
 2  * 真實身份(至關於例子中的周杰倫本人)
 3  * @author CL
 4  *
 5  */
 6 public class RealStar implements Star {
 7 
 8     @Override
 9     public void confer() {
10         System.out.println("周杰倫去面談");
11     }
12 
13     @Override
14     public void signConstract() {
15         System.out.println("周杰倫去籤合同");
16     }
17 
18     @Override
19     public void bookTicket() {
20         System.out.println("周杰倫去訂票");
21     }
22 
23     @Override
24     public void sing() {
25         System.out.println("周杰倫去唱歌");
26     }
27 
28     @Override
29     public void collectMoney() {
30         System.out.println("周杰倫去收款");        
31     }
32 
33 }

  (3)定義代理角色

 1 /**
 2  * 代理身份(至關於例子中的周杰倫的經紀人)
 3  * @author CL
 4  *
 5  */
 6 public class ProxyStar implements Star {
 7     private Star star;
 8     
 9     public ProxyStar(Star star) {
10         this.star = star;
11     }
12 
13     @Override
14     public void confer() {
15         System.out.println("經紀人去面談");
16     }
17 
18     @Override
19     public void signConstract() {
20         System.out.println("經紀人去籤合同");
21     }
22 
23     @Override
24     public void bookTicket() {
25         System.out.println("經紀人去訂票");
26     }
27 
28     @Override
29     public void sing() {
30         star.sing();
31     }
32 
33     @Override
34     public void collectMoney() {
35         System.out.println("經紀人去收款");
36     }
37 
38 }

  (4)測試

 1 /**
 2  * 客戶端
 3  *     只和經紀人聯繫
 4  * @author CL
 5  *
 6  */
 7 public class Client {
 8 
 9     public static void main(String[] args) {
10         Star real = new RealStar();
11         Star proxy = new ProxyStar(real);
12         
13         //面談
14         proxy.confer();
15         //籤合同
16         proxy.signConstract();
17         //訂票
18         proxy.bookTicket();
19         //唱歌
20         proxy.sing();
21         //收款
22         proxy.collectMoney();
23     }
24 }

  控制檯輸出:

經紀人去面談
經紀人去籤合同
經紀人去訂票
周杰倫去唱歌
經紀人收款

3、代理模式之動態代理

  JDK自帶的動態代理:

    ① 在客戶端,java.lang.reflect.Proxy

     做用:動態生成代理類和對象

    ② 實現java.lang.reflect.InvocationHandler(處理器接口)

     能夠經過invoke方法實現對真實角色的代理訪問

     每次經過Proxy生成代理類對象時都要指定對應的處理器對象

  (1)建立抽象角色

 1 public interface Star {
 2     /**
 3      * 面談 
 4      */
 5     void confer();
 6     /**
 7      * 籤合同
 8      */
 9     void signConstract();
10     /**
11      * 訂票
12      */
13     void bookTicket();
14     /**
15      * 唱歌
16      */
17     void sing();
18     /**
19      * 收款
20      */
21     void collectMoney();
22 }

  (2)建立真實角色

 1 /**
 2  * 真實身份(至關於例子中的周杰倫本人)
 3  * @author CL
 4  *
 5  */
 6 public class RealStar implements Star {
 7 
 8     @Override
 9     public void confer() {
10         System.out.println("周杰倫去面談");
11     }
12 
13     @Override
14     public void signConstract() {
15         System.out.println("周杰倫去籤合同");
16     }
17 
18     @Override
19     public void bookTicket() {
20         System.out.println("周杰倫去訂票");
21     }
22 
23     @Override
24     public void sing() {
25         System.out.println("周杰倫去唱歌");
26     }
27 
28     @Override
29     public void collectMoney() {
30         System.out.println("周杰倫去收款");        
31     }
32 
33 }

  (3)建立代理角色的處理器

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 
 4 /**
 5  * 代理角色的處理類
 6  * jdk自帶的動態代理
 7  * @author CL
 8  *
 9  */
10 public class StarHandler implements InvocationHandler {
11     private Star realStar;
12     
13     public StarHandler(Star realStar) {
14         this.realStar = realStar;
15     }
16 
17     //經過invoke方法實現對真實角色的代理訪問
18     @Override
19     public Object invoke(Object proxy, Method method, Object[] args)
20             throws Throwable {
21         Object obj = null;
22         
23         System.out.print("在執行真實角色的方法以前的處理,好比-->");
24         System.out.println("面談,籤合同,訂票");
25         
26         if (method.getName().equals("sing")) {
27             obj = method.invoke(realStar, args);
28         }
29         
30         System.out.print("在執行真實角色的方法以後的處理,好比-->");
31         System.out.println("收款");
32         
33         return obj;
34     }
35 
36 }

  (4)測試

 1 import java.lang.reflect.Proxy;
 2 
 3 /**
 4  * 測試JDK自帶的動態代理
 5  * @author CL
 6  *
 7  */
 8 public class Client {
 9 
10     public static void main(String[] args) {
11         Star realStar = new RealStar();
12         
13         StarHandler handler = new StarHandler(realStar);
14         
15         Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class}, handler);
16         
17         proxy.sing();
18     }
19 }

  控制檯輸出:

在執行真實角色的方法以前的處理,好比-->面談,籤合同,訂票
周杰倫去唱歌
在執行真實角色的方法以後的處理,好比-->收款
相關文章
相關標籤/搜索