Java設計模式【代理模式】

一、前言

1.1 背景

在不改變原有代碼的基礎上,對方法進行功能性的增強;

1.2 簡介

代理模式是一種結構型模式,為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

組成

  • 抽象主體(Subject):通過接口或抽象類聲明真實主體實現的業務方法
  • 代理(Proxy):實現抽象主體,是真實主體的代理,通過真實主體的業務邏輯方法來實現抽象方法,并可以附加自己的操作
  • 真實主體(RealSubject):實現抽象主體,定義真實主體所要實現的業務邏輯,供代理主體調用

優點

  • 職責清晰
  • 中介的作用、保護目標對象的作用
  • 高擴展性

二、三種實現

  • 靜態代理
  • JDK動態代理
  • Cglib動態代理

此處以代駕舉例:抽象主體(Driver),代理(ProxyDriver),真實主體(RealDriver)

2.1 靜態代理

缺點

  • 代理類過多:代理對象需要和目標對象實現相同的接口或父類
  • 難以維護:一旦接口中增加了方法后,目標對象和代理對象都需要維護
package com.qiangesoft.design.structural.proxy;/*** 靜態代理*/
public class StaticProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();Driver driver = new ProxyDriver(realDriver);driver.drive("奧迪A6L");}
}/*** 駕駛員接口*/
interface Driver {void drive(String car);
}/*** 真實駕駛員*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被開回家了");}
}/*** 代理駕駛員*/
class ProxyDriver implements Driver {private RealDriver realDriver;public ProxyDriver(RealDriver realDriver) {this.realDriver = realDriver;}@Overridepublic void drive(String car) {System.out.println("代駕取鑰匙");realDriver.drive(car);System.out.println("代駕還鑰匙");}
}

2.2 JDK動態代理

特點

  • 利用JDK的API動態的在內存中構建代理對象(需指定目標對象實現接口的類型、代理對象)
  • 目標對象一定要實現接口,否則不能用動態代理
package com.qiangesoft.design.structural.proxy.jdk;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** jdk動態代理*/
public class JdkDynamicProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();ProxyDriver proxyDriver = new ProxyDriver(realDriver);Driver proxy = (Driver) proxyDriver.getProxyInstance();// 使用代理對象來調用抽象方法proxy.drive("奧迪A6L");}
}/*** 駕駛員接口*/
interface Driver {void drive(String car);
}/*** 真實駕駛員*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被開回家了");}
}/*** 代理駕駛員*/
class ProxyDriver implements InvocationHandler {private Object realDriver;public ProxyDriver(RealDriver realDriver) {this.realDriver = realDriver;}public Object getProxyInstance() {// 使用Proxy類的靜態方法newProxyInstance來動態地創建一個代理對象,傳入真實主題對象的類加載器、接口和處理器return Proxy.newProxyInstance(realDriver.getClass().getClassLoader(), realDriver.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代駕取鑰匙");Object result = method.invoke(realDriver, args);System.out.println("代駕還鑰匙");return result;}
}

2.3 Cglib動態代理

特點

  • 通過生成目標對象的子類實現代理
  • 需要引入cglib的jar包
  • 目標對象的類不能是final(類不能被繼承)
  • 目標對象的方法如果有final(方法不能被重寫)/static(非對象的方法)修飾,不會被執行。

引入依賴

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

代碼實現

package com.qiangesoft.design.structural.proxy.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** cglib動態代理*/
public class CglibDynamicProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();ProxyDriver proxyDriver = new ProxyDriver(realDriver);RealDriver proxy = (RealDriver) proxyDriver.getProxyInstance();proxy.drive("奧迪A6L");}
}/*** 駕駛員接口*/
interface Driver {void drive(String car);
}/*** 真實駕駛員*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被開回家了");}
}/*** 代理駕駛員*/
class ProxyDriver implements MethodInterceptor {private Object realDriver;public ProxyDriver(Object realDriver) {this.realDriver = realDriver;}public Object getProxyInstance() {// 1.工具類Enhancer enhancer = new Enhancer();// 2.設置父類enhancer.setSuperclass(realDriver.getClass());// 3.設置回調函數enhancer.setCallback(this);// 4.創建子類(代理對象)return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("代駕取鑰匙");Object result = method.invoke(realDriver, args);System.out.println("代駕還鑰匙");return result;}
}

三、總結

  • 如果加入容器的目標對象有實現接口,用JDK代理
  • 如果目標對象沒有實現接口,用Cglib代理
  • 如果目標對象實現了接口,且強制使用cglib代理,則會使用cglib代理。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697899.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697899.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697899.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

axure9.0 工具使用思考

原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】快速原型設計工具原型設計軟件【AxureRP】…

CentOS使用Docker搭建Halo網站并實現無公網ip遠程訪問

&#x1f525;博客主頁&#xff1a; 小羊失眠啦. &#x1f3a5;系列專欄&#xff1a;《C語言》 《數據結構》 《C》 《Linux》 《Cpolar》 ??感謝大家點贊&#x1f44d;收藏?評論?? 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&…

【華為OD機試真題 C++語言】483、中文分詞模擬器 | 機試真題+思路參考+代碼解析(C卷)

文章目錄 一、題目??題目描述??輸入輸出??樣例1??樣例2??樣例3二、思路參考三、代碼參考作者:KJ.JK??個人博客首頁: KJ.JK ??專欄介紹: 華為OD機試真題匯總,定期更新華為OD各個時間階段的機試真題,每日定時更新,本專欄將使用C++語言進行更新解答,包含真…

創紀錄:英偉達市值一日增 2770 億美元;Xiaomi 14 Ultra 正式發布丨 RTE 開發者日報 Vol.150

開發者朋友們大家好&#xff1a; 這里是 「RTE 開發者日報」 &#xff0c;每天和大家一起看新聞、聊八卦。我們的社區編輯團隊會整理分享 RTE &#xff08;Real Time Engagement&#xff09; 領域內「有話題的 新聞 」、「有態度的 觀點 」、「有意思的 數據 」、「有思考的 文…

mysql 用戶權限管理

mysql使用系統庫mysql的user表來存儲用戶信息。mysql.user表詳細的記錄了用戶名&#xff0c;對應的允許連接的主機信息還有各種全局權限標識位。 用戶管理 創建用戶 CREATE USER 用戶名host主機 IDENTIFIED BY 密碼;上面是創建用的基本命令&#xff0c;指定了用戶名&#xf…

Selenium基礎知識

一、環境搭建&#xff08;以java為例&#xff09; 1.下載chrome瀏覽器 https://www.google.cn/intl/zh-CN/chrome/ 2.查看chrome瀏覽器版本 設置關于chrome 3.下載chrome瀏覽器驅動 下載瀏覽器對應版本的 ChromeDriver - WebDriver for Chrome - Downloads 120以上版本&…

WordPress使用

WordPress功能菜單 儀表盤 可以查看網站基本信息和內容。 文章 用來管理文章內容&#xff0c;分類以及標簽。編輯文章以及設置分類標簽&#xff0c;分類和標簽可以被添加到 外觀-菜單 中。 分類名稱自定義&#xff1b;別名為網頁url鏈接中的一部分&#xff0c;最好別設置為中文…

概率密度函數(PDF)與神經網絡中的激活函數

原創:項道德(daode3056,daode1212) 在量子力學中&#xff0c;許多現象都是統計的結果&#xff0c;基本上用的是正態分布&#xff0c;然而&#xff0c;從本質上思考&#xff0c;應該還存在低階的分布&#xff0c;標準的正態分布是它的極限&#xff0c;這樣一來&#xff0c;或許在…

python中多線程使用

前言 記錄下Python中多線程使用 標題 前言簡介使用demo 簡介 Python 中的多線程主要通過 threading 模塊來實現。多線程是一種并發編程的方式&#xff0c;允許程序在同一時間執行多個線程&#xff0c;每個線程執行不同的任務。然而需要注意的是&#xff0c;在 Python 中由于 …

【前端素材】推薦優質后臺管理系統Spica Admin平臺模板(附源碼)

一、需求分析 后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;它通常作為一個獨立的后臺界面存在&#xff0c;供管理員或特定用戶使用。下面詳細分析后臺管理系統的定義和功能&#xff1a; 1. 定義 后臺管理系統是一個用于管理和控制網站、應用程序或系統…

【安全】大模型安全綜述

大模型相關非安全綜述 LLM演化和分類法 A survey on evaluation of large language models,” arXiv preprint arXiv:2307.03109, 2023.“A survey of large language models,” arXiv preprint arXiv:2303.18223, 2023.“A survey on llm-gernerated text detection: Necess…

刷題日記-Day1- Leedcode-704. 二分查找,27. 移除元素-Python實現

704 二分查找 鏈接&#xff1a;https://leetcode.cn/problems/binary-search/description/ 給定一個 n 個元素有序的&#xff08;升序&#xff09;整型數組 nums 和一個目標值 target &#xff0c;寫一個函數搜索 nums 中的 target&#xff0c;如果目標值存在返回下標&#xf…

vue3 toRefs之后的變量修改方法

上效果 修改值需要帶上解構之前的對象名obj&#xff0c; changeName:()>{ // toRefs 解決后變量修改值方法&#xff1a; 解構前變量.字段新值 obj.name FEIFEI; } } 案例源碼 <!DOCTYPE html> <html> <head><me…

如何在pgAdmin中用替換的值更新jsonb列?

我有一個名為files的PostgreSQL表&#xff0c;其中包括一個名為formats的jsonb表。雖然有些行是[null]&#xff0c;但其他行具有此結構的對象&#xff1a; {"thumbnail": {"ext": ".jpg","url": "https://some-url.com/image01.…

Vue | (四)使用Vue腳手架(上) | 尚硅谷Vue2.0+Vue3.0全套教程

文章目錄 &#x1f4da;初始化腳手架&#x1f407;創建初體驗&#x1f407;分析腳手架結構&#x1f407;關于render&#x1f407;查看默認配置 &#x1f4da;ref與props&#x1f407;ref屬性&#x1f407;props配置項 &#x1f4da;混入&#x1f4da;插件&#x1f4da;scoped樣…

idea配置javafx

一、下載sdk 在jdk8之后,需要下載sdk包 ??javafx-sdk-18.zip 這里適用的jkd版本如圖 二、配置 創建一個項目之后,進行如下配置,將sdk導入到項目中 配置啟動參數 可以使用-號將之前的去掉&

同步 BUCK 與 異步 BUCK 的區別

上篇文章介紹 BUCK 基本拓撲電路工作原理&#xff0c;BUCK 電路如下圖&#xff1a; 因為二極管的存在&#xff0c;只需要控制一個 MOS 管開關&#xff0c;一般將該電路稱為異步 BUCK 電路&#xff0c;如果把這個二極管換為 MOS 管&#xff0c;如下圖&#xff1a; 該電路用到了兩…

vue Threejs實現任意畫線(鼠標點擊畫線)

Threejs實現任意畫線(鼠標點擊畫線) 鼠標左鍵單擊添加點鼠標右鍵回退到上一個點,并繼續畫按住shift可以畫平行于x軸或平行于z軸的線按Esc完成畫線

【leetcode題解C++】121.買賣股票的最佳時機 and 122.買賣股票的最佳時機II and 55.跳躍游戲 and 45.跳躍游戲II

121. 買賣股票的最佳時機 給定一個數組 prices &#xff0c;它的第 i 個元素 prices[i] 表示一支給定股票第 i 天的價格。 你只能選擇 某一天 買入這只股票&#xff0c;并選擇在 未來的某一個不同的日子 賣出該股票。設計一個算法來計算你所能獲取的最大利潤。 返回你可以從…

汽車信息安全概述

隨著智能網聯汽車的迅猛發展&#xff0c;車輛不再是簡單的交通工具&#xff0c;而是集數據收集、處理與通信于一體的移動智能終端。然而&#xff0c;這一變革也使得汽車成為黑客攻擊的新目標。汽車信息安全問題日益凸顯&#xff0c;成為行業關注的焦點。本文將深入探討汽車信息…