【結構型模式-代理模式】

概述

由于某些原因需要給某對象提供一個代理以控制該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作為訪問對象與目標對象之間的中介。
Java中的代理按照代理類生成時機不同又分為靜態代理和動態代理。靜態代理代理類在編譯期就生成,而動態代理類則是在Java運行時動態生成。動態代理又有JDK代理和CGLib代理兩種。

結構

代理(Proxy)模式分為三種角色:

  • 抽象主題(Subject)類:通過接口或抽象類聲明真實主題和代理對象實現的業務方法。
  • 真實主題(Real Subject)類:實現了抽象主題中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
  • 代理(Proxy)類:提供了與真實主題相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或拓展真實主題的功能。
    在這里插入圖片描述
靜態代理
package com.syn.proxy.static_proxy;/*賣票規范*/
public interface SellTickets {void sell();
}
package com.syn.proxy.static_proxy;/*火車站賣票*/
public class TrainStation implements  SellTickets{@Overridepublic void sell() {System.out.println("火車站賣票.");}
}
package com.syn.proxy.static_proxy;/*代理點*/
public class Proxypoint implements SellTickets{private TrainStation trainStation = new TrainStation();@Overridepublic void sell() {System.out.println("代理收取費用.");trainStation.sell();}
}
package com.syn.proxy.static_proxy;/*客戶端買票*/
public class Client {public static void main(String[] args) {/*創建代理類*/Proxypoint proxypoint = new Proxypoint();/*買票*/proxypoint.sell();}
}

在這里插入圖片描述

JDK動態代理
package com.syn.proxy.jdk_proxy;/*賣票規范*/
public interface SellTickets {void sell();
}
package com.syn.proxy.jdk_proxy;/*火車站賣票*/
public class TrainStation implements SellTickets {@Overridepublic void sell() {System.out.println("火車站賣票.");}
}
package com.syn.proxy.jdk_proxy;import com.syn.proxy.static_proxy.SellTickets;
import com.syn.proxy.static_proxy.TrainStation;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*獲取代理對象的工廠類*/
public class ProxyFactory {/*聲明目標對象*/private TrainStation trainStation = new TrainStation();public SellTickets getProxyObject(){/*返回代理對象*/SellTickets proxyObject  =  (SellTickets) Proxy.newProxyInstance(/*用于加載代理類,可以通過目標對象獲取類加載器*/trainStation.getClass().getClassLoader(),/*代理類實現的接口字節碼對象*/trainStation.getClass().getInterfaces(),/*代理對象的調用處理程序*/new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理收費(JDK動態版本).");/*執行目標對象方法*/Object object = method.invoke(trainStation,args);return object;}});return proxyObject;}
}
package com.syn.proxy.jdk_proxy;import com.syn.proxy.static_proxy.SellTickets;public class Client {public static void main(String[] args) {/*創建代理工廠*/ProxyFactory proxyFactory = new ProxyFactory();/*使用工廠獲取代理對象*/SellTickets proxyObject = proxyFactory.getProxyObject();/*調用目標方法*/proxyObject.sell();}
}

在這里插入圖片描述

CDLIB動態代理

對于上面的案例,如果沒有定義SellTickets接口,只定義了TrainStation。很顯然JDK動態代理便無法使用了,因為JDK動態代理要求必須定義接口,對接口進行代理。
CGLIB是一個功能強大,高性能的代碼生成包,它為沒有實現接口的類提供代理,為JDK的動態代理提供了很好的補充。
需要引入maven包

    <dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency></dependencies>
package com.syn.proxy.cglib_proxy;/*火車站賣票*/
public class TrainStation{public void sell() {System.out.println("火車站賣票.");}
}
package com.syn.proxy.cglib_proxy;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*代理對象工廠*/
public class ProxyFactory implements MethodInterceptor {/*聲明火車站對象*/private TrainStation trainStation = new TrainStation();public TrainStation getProxyObject(){/*創建Enhancer對象,類似于JDK代理中的Proxy類*/Enhancer enhancer = new Enhancer();/*設置父類的字節碼對象*/enhancer.setSuperclass(TrainStation.class);/*設置回調函數*/enhancer.setCallback(this);/*創建代理對象*/return (TrainStation) enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("代理收費(CGLIB動態版本).");/*要調用目標對象的方法*/return method.invoke(trainStation,objects);}
}
package com.syn.proxy.cglib_proxy;public class Client {public static void main(String[] args) {/*創建代理工廠對象*/ProxyFactory proxyFactory = new ProxyFactory();/*獲取代理對象*/TrainStation proxyObject = proxyFactory.getProxyObject();/*調用代理對象的sell方法賣票*/proxyObject.sell();}
}

在這里插入圖片描述

三種代理對比

  • jdk代理和CGLIB代理

使用CGLib實現動態代理,CGLib底層采用ASM字節碼生成框架,使用字節碼技術生成代理類,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明為final的類或者方法進行代理,因為CGLib原理是動態生成被代理類的子類。
在JDK1.6、JDK1.7、JDK1.8逐步對JDK動態代理優化之后,在調用次數較少的情況下,JDK代理效率高于CGLib代理效率,只有當進行大量調用的時候,JDK1.6和JDK1.7比CGLib代理效率低一點,但是到JDK1.8的時候,JDK代理效率高于CGLib代理。所以如果有接口使用JDK動態代理,如果沒有接口使用CGLIB代理。

  • 動態代理和靜態代理

動態代理與靜態代理相比較,最大的好處是接口中聲明的所有方法都被轉移到調用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在接口方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。
如果接口增加一個方法,靜態代理模式除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的復雜度。而動態代理不會出現該問題。

優缺點

優點:

  • 代理模式在客戶端與目標對象之間起到一個中介作用和保護目標對象的作用;
  • 代理對象可以擴展目標對象的功能;
  • 代理模式能將客戶端與目標對象分離,在一定程度上降低了系統的耦合度。

缺點:

  • 增加了系統的復雜度。

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

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

相關文章

情感分析新紀元:Transformer模型的革命性應用

情感分析新紀元&#xff1a;Transformer模型的革命性應用 情感分析&#xff0c;又稱為意見挖掘&#xff0c;是自然語言處理&#xff08;NLP&#xff09;領域中的一項重要任務&#xff0c;它旨在從文本數據中識別和提取主觀信息&#xff0c;判斷文本所表達的情感傾向&#xff0…

MACOS查看硬盤讀寫量

一、安裝Homebrew 按照提示進行安裝 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"二、安裝smartmontools brew install smartmontools三、查看硬盤讀寫量等信息 sudo smartctl -a /dev/disk0

WPF 制作一個文字漂浮提示框

WPF好像沒有自帶的文字提示漂浮&#xff0c;我們可以定制一個。 效果如下&#xff1a; xaml xaml如下&#xff1a; <Window x:Class"GroupServer.MsgTip"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://sc…

谷粒商城學習筆記-23-分布式組件-SpringCloud Alibaba-Nacos配置中心-簡單示例

之前已經學習了使用Nacos作為注冊中心&#xff0c;這一節學習Nacos另外一個核心功能&#xff1a;配置中心。 一&#xff0c;Nacos配置中心簡介 Nacos是一個易于使用的平臺&#xff0c;用于動態服務發現和配置管理。作為配置中心&#xff0c;Nacos提供了以下核心功能和優勢&am…

微軟推出全新的學習網站 Microsoft Learn

微軟官方宣布推出全新的學習網站 Microsoft Learn&#xff0c;供開發人員學習 Microsoft 技術。 該網站包含所有 Microsoft 產品和服務(從 HoloLens 到 Azure)的技術文檔。提供了超過 80 小時的學習內容&#xff0c;涉及 Azure、Dynamics 365、PowerApps、Microsoft Flow 和 Po…

VSTO插件功能介紹-清除空行【進化過程】

大家看到的是完成的成果&#xff0c; 可能不知在其中&#xff0c;寫碼人的艱辛 今天的主要是記錄【進化過程】 用于自勉&#xff0c;與大家共勉&#xff0c;努力 文章中的代碼你可復制使用哦 想要的效果若用戶選擇了區域&#xff0c;選擇確定Button對此區域&#xff0c;進行清除…

代碼隨想錄算法訓練營Day64|拓撲排序(卡碼網117)、dijkstra樸素版

拓撲排序 117. 軟件構建 (kamacoder.com) 拓撲排序簡單的說是將一個有向圖轉為線性的排序。 它將圖中的所有結點排序成一個線性序列&#xff0c;使得對于任何的邊uv&#xff0c;結點u在序列中都出現在結點v之前&#xff0c;這樣的序列滿足圖中所有的前驅-后繼關系。 拓撲排…

vue 插槽 【slot】

文章目錄 默認插槽具名插槽作用域插槽 默認插槽 父組件中&#xff1a;<Category title"今日熱門游戲"><ul><li v-for"g in games" :key"g.id">{{ g.name }}</li></ul></Category> 子組件中&#xff1a;<…

9. 機器人數目

題目描述 本題為填空題&#xff0c;只需要算出結果后&#xff0c;在代碼中使用輸出語句將所填結果輸出即可。 少年宮新近郵購了小機器人配件&#xff0c;共有3類。 &#x1d434;A 類含有&#xff1a;88 個輪子&#xff0c;11 個傳感器&#xff1b; &#x1d435;B 類含有:…

深入理解基本數據結構:棧詳解

引言 在計算機科學中&#xff0c;數據結構是存儲、組織和管理數據的方式。棧是一種重要的線性數據結構&#xff0c;廣泛應用于各種編程場景。在這篇博客中&#xff0c;我們將詳細探討棧的定義、特點、操作及其在不同編程語言中的實現。 什么是棧&#xff1f; **棧&#xff08…

java動態代理的使用和代碼示例

文章目錄 1. 簡介2. 代碼3. 參考鏈接 1. 簡介 代理類在程序運行時創建的代理方式被成為動態代理。在靜態代理中&#xff0c;代理類&#xff08;RenterProxy&#xff09;是自己已經定義好了的&#xff0c;在程序運行之前就已經編譯完成。而動態代理是在運行時根據我們在Java代碼…

前端vue 實現取色板 的選擇

大概就是這樣的 一般的web端框架 都有自帶的 的 比如 ant-design t-design 等 前端框架 都是帶有這個的 如果遇到沒有的我們可以自己嘗試開發一下 簡單 的 肯定比不上人家的 但是能用 能看 說的過去 我直接上代碼了 其實這個取色板 就是一個input type 是color 的input …

CTF學習記錄(一)——Web基礎

目錄 Web基礎Web基礎常用工具ncat(網絡工具中的瑞士軍刀&#xff0c;功能齊全)curl(一個工作在命令行的發起HTTP請求的工具)BurpSuite(Web核心抓包工具)Hackbar插件SwitchyOmega 代理插件&#xff08;非常牛逼&#xff09;Wappalyzer 技術判斷插件EditThisCookie 插件Postman 接…

深入理解Spring Boot中的定時任務調度

深入理解Spring Boot中的定時任務調度 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 1. Spring Boot中的定時任務概述 在現代應用程序開發中&#xff0c;定時任務調度是一項非常常見和重要的功能…

【計算機網絡03】不花錢怎么搭建一個網絡實驗室

使用GNS3和虛擬機搭建網絡實驗室 1、安裝抓包工具分析數據包2、定義和使用抓包篩選器3、安裝和配置GNS34、配置路由器和VPCS5、使用WireShark捕獲GNS3網絡數據包6、VMware創建虛擬機7、使用思科PacketTracer 1、安裝抓包工具分析數據包 官網安裝wireshark&#xff1a;https://…

python怎么判斷字符串以什么結尾

在python編輯器中新建一個data.py。 寫上自己的注釋。 然后新建一個變量testname。 利用endswith來判斷字符串是不是以“ar”結尾。 將結果打印出來。 選擇“run”->“run”。 運行該程序&#xff0c;如果是&#xff0c;就會返回true。

JavaScript-日期對象

日期對象 作用&#xff1a;用來表示時間的對象 獲取當前時間 const datenew Date();console.log(date);可以得到日期對象&#xff0c;里面的屬性有星期&#xff0c;年月日&#xff0c;時分秒 獲取指定時間 const datenew Date(2023-05-01);console.log(date); 獲取時間戳 時間…

PyTorch深度學習實戰(45)——強化學習

PyTorch深度學習實戰&#xff08;45&#xff09;——強化學習 0. 前言1. 強化學習基礎1.1 基本概念1.2 馬爾科夫決策過程1.3 目標函數1.4 智能體學習過程 2. 計算狀態值3. 計算狀態-動作值4. Q 學習4.1 Q 值4.2 Gym環境4.3 構建 Q 表4.4 探索-利用策略 小結系列鏈接 0. 前言 強…

悠律凝聲環開放式耳機體驗:強勁低音、高顏值設計

最近發現了一款潮酷的開放式耳機&#xff0c;不僅顏值抗打&#xff0c;更重要的是能在嘈雜的環境中提供給我一份寧靜的沉浸式音樂體驗&#xff0c;號稱是開放音頻中的重低音之王&#xff0c;它就是悠律凝聲環開放式耳機。 這款耳機無論其外觀設計、音質效果、性價比以及續航能力…

通勤數據:Comma2k19 數據集

A Commute in Data: The comma2k19 Dataset 通勤數據&#xff1a;Comma2k19 數據集 https://arxiv.org/pdf/1812.05752v1 Abstract— comma.ai presents comma2k19, a dataset of over 33 hours of commute in California’s 280 highway. This means 2019 segments, 1 minut…