設計模式之☞代理模式

  • 2019 年 10 月 14 日
  • 筆記

一、代理模式的作用

  • 將主要業務與次要業務進行松耦合的組裝

二、代理模式本質

  • 監控行為的特徵

例子:

  <input type=”button” onclick=”處理函數”>

三、生活案例

案例:飯前便後要洗手

分析:

  1.分析出主要業務和次要業務

  【主要業務】:吃飯,上廁所

  【次要業務】:洗手

  2.JDK代理模式實現

    2.1、介面角色:定義所有需要被監聽行為

BaseService.java

1 package com.chenyanbin.service;  2  3 /*  4  * 只有需要被監控的行為才有資格在這裡聲明  5  */  6 public interface BaseService {  7     public void Eat();  8     public void Wc();  9 }

    2.2、介面實現類:中國人、印度人

Person.java

 1 package com.chenyanbin.serviceImpl;   2   3 import com.chenyanbin.service.BaseService;   4   5 public class Person implements BaseService {   6   7     @Override   8     public void Eat() { //主要業務,代理模式要求開發任務只關心主要業務   9         System.out.println("使用筷子吃飯");  10     }  11  12     @Override  13     public void Wc() {  14         System.out.println("測試地球重力是否存在");  15     }  16 }

    2.3、通知類:1)次要業務進行具體實現    2)通知JVM,當前被攔截的主要業務方法與次要業務方法應該如何綁定執行

Invaction.java

 1 package com.chenyanbin.util;   2   3 import java.lang.reflect.InvocationHandler;   4 import java.lang.reflect.Method;   5   6 import com.chenyanbin.service.BaseService;   7   8 public class Invaction implements InvocationHandler {   9     private BaseService obj;// 具體被監控對象  10  11     public Invaction(BaseService param) {  12         this.obj = param;  13     }  14  15     /*  16      * invoke方法:被監控行為將要執行時,會被JVM攔截,被監控行為和行為實現方會被作為參數輸送到invoke  17      * ***通知JVM,這個被攔截方法是如何與當前次要業務方法綁定實現 invoke方法三個參數 小明.Eat();//JVM攔截  18      * Eat方法封裝為Method類型方法 Eat方法運行時所有的實參封裝到Object[] 將負責監控小明的代理對象作為invoke方法第一個參數  19      *  20      */  21     @Override  22     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  23         // 0.局部變數,接受主要業務方法執行完畢後返回值  24         Object value;  25         // 1.確認當前被攔截行為  26         String methodName = method.getName();  27         // 2.根據被攔截行為不同,決定主要業務和次要業務如何綁定執行  28         if ("Eat".equals(methodName)) { // 飯前要洗手  29             Wash();// 洗手  30             value = method.invoke(this.obj, args);// 當前主要業務  31         } else { // 便後洗手  32             value = method.invoke(this.obj, args);// 當前主要業務  33             Wash();// 洗手  34         }  35         return value; //返回被攔截方法  36     }  37  38     // 次要業務  39     public void Wash() {  40         System.out.println("--------洗手--------");  41     }  42 }

    2.4、監控對象(代理對象):1)被監控實例對象   2)需要被監控行為   3)具體通知類實例對象

ProxyFactory.java

 1 package com.chenyanbin.util;   2   3 import java.lang.reflect.InvocationHandler;   4 import java.lang.reflect.Proxy;   5   6 import com.chenyanbin.service.BaseService;   7   8 public class ProxyFactory {   9     /*  10      * JDK動態代理模式下,代理對象的數據類型 應該由監控行為來描述 參數:Class文件,監控類  11      */  12     public static BaseService build(Class classFile) throws Exception {  13         //1.創建被監控實例對象  14         BaseService obj = (BaseService) classFile.getDeclaredConstructor().newInstance();  15         //2.創建通知對象  16         InvocationHandler adviser=new Invaction(obj);  17         //3.向JVM申請負責監控obj對象指定行為的監控對象(代理對象)  18         /*  19          * loader:被監控對象隸屬的類文件在記憶體中真實地址  20          * interfaces:被監控對象隸屬的類文件實現介面  21          * h:監控對象發現小明要執行被監控行為,應該由哪一個通知對象進行輔助  22          */  23         BaseService $proxy=(BaseService)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), adviser);  24         return $proxy;  25     }  26 }

測試類

TestMain.java

 1 import com.chenyanbin.service.BaseService;   2 import com.chenyanbin.serviceImpl.Person;   3 import com.chenyanbin.util.ProxyFactory;   4   5 public class TestMain {   6   7     public static void main(String[] args) throws Exception {   8         //mike.Eat();   9 //        Person mike=new Person();  10         BaseService mike = ProxyFactory.build(Person.class);  11         mike.Eat();  12     }  13 }

吃飯

 

 上廁所

項目目錄結構