自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇學(xué)會常見的代理模式

開發(fā) 前端
相信大家都聽過代理模式,有靜態(tài)代理,JDK動態(tài)代理,Cglib代理(Spring的內(nèi)容)。接下來,千羽和大家一起學(xué)習(xí)一下這些代理模式各有優(yōu)缺點(diǎn)和相應(yīng)的使用場景。

1. 代理模式概述

2. 代理模式的結(jié)構(gòu)與實(shí)現(xiàn)

3. 代理模式的應(yīng)用實(shí)例

4. 遠(yuǎn)程代理

5. 虛擬代理

6. Java動態(tài)代理

7. 代理模式的優(yōu)缺點(diǎn)與適用環(huán)境

“Github:https://github.com/nateshao/design-demo/tree/main/JavaDesignPatterns/15-proxy

1. 代理模式概述

相信大家都聽過代理模式,有靜態(tài)代理,JDK動態(tài)代理,Cglib代理(Spring的內(nèi)容)。接下來,千羽和大家一起學(xué)習(xí)一下這些代理模式各有優(yōu)缺點(diǎn)和相應(yīng)的使用場景。

商品代購示意圖:

分析

  • 代購商品:顧客 -> 代購網(wǎng)站 -> 商品
  • 軟件開發(fā):客戶端 -> 代理對象 -> 真實(shí)對象

還有這種類型

定義:

代理模式:給某一個(gè)對象提供一個(gè)代理或占位符,并由代理對象來控制對原對象的訪問。

  1. 引入一個(gè)新的代理對象
  2. 代理對象在客戶端對象和目標(biāo)對象之間起到中介的作用
  3. 去掉客戶不能看到的內(nèi)容和服務(wù)或者增添客戶需要的額外的新服務(wù)

代理模式的結(jié)構(gòu)

代理模式包含以下3個(gè)角色:

  • Subject(抽象主題角色)
  • Proxy(代理主題角色)
  • RealSubject(真實(shí)主題角色)

2. 代理模式的結(jié)構(gòu)與實(shí)現(xiàn)

抽象主題類典型代碼:

  1. public abstract class Subject { 
  2.  public abstract void request(); 

真實(shí)主題類典型代碼:

  1. public class RealSubject extends Subject{ 
  2.     public void request() { 
  3.           //業(yè)務(wù)方法具體實(shí)現(xiàn)代碼 
  4.     } 

代理類典型代碼:

  1. public class Proxy extends Subject { 
  2.     private RealSubject realSubject = new RealSubject();  //維持一個(gè)對真實(shí)主題對象的引用  
  3.     public void preRequest() { 
  4.         …... 
  5.     } 
  6.   
  7.     public void request() { 
  8.         preRequest(); 
  9.         realSubject.request();  //調(diào)用真實(shí)主題對象的方法 
  10.         postRequest(); 
  11.     } 
  12.   
  13.     public void postRequest() { 
  14.         …… 
  15.     } 

幾種常見的代理模式

  • 遠(yuǎn)程代理(Remote Proxy):為一個(gè)位于不同的地址空間的對象提供一個(gè)本地的代理對象,這個(gè)不同的地址空間可以在同一臺主機(jī)中,也可以在另一臺主機(jī)中,遠(yuǎn)程代理又稱為大使(Ambassador)
  • 虛擬代理(Virtual Proxy):如果需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對象,先創(chuàng)建一個(gè)消耗相對較小的對象來表示,真實(shí)對象只在需要時(shí)才會被真正創(chuàng)建
  • 保護(hù)代理(Protect Proxy):控制對一個(gè)對象的訪問,可以給不同的用戶提供不同級別的使用權(quán)限
  • 緩沖代理(Cache Proxy):為某一個(gè)目標(biāo)操作的結(jié)果提供臨時(shí)的存儲空間,以便多個(gè)客戶端可以共享這些結(jié)果
  • 智能引用代理(Smart Reference Proxy):當(dāng)一個(gè)對象被引用時(shí),提供一些額外的操作,例如將對象被調(diào)用的次數(shù)記錄下來等

3. 代理模式的應(yīng)用實(shí)例

某軟件公司承接了某信息咨詢公司的收費(fèi)商務(wù)信息查詢系統(tǒng)的開發(fā)任務(wù),該系統(tǒng)的基本需求如下:

在進(jìn)行商務(wù)信息查詢之前用戶需要通過身份驗(yàn)證,只有合法用戶才能夠使用該查詢系統(tǒng);

在進(jìn)行商務(wù)信息查詢時(shí)系統(tǒng)需要記錄查詢?nèi)罩?,以便根?jù)查詢次數(shù)收取查詢費(fèi)用。

該軟件公司開發(fā)人員已完成了商務(wù)信息查詢模塊的開發(fā)任務(wù),現(xiàn)希望能夠以一種松耦合的方式向原有系統(tǒng)增加身份驗(yàn)證和日志記錄功能,客戶端代碼可以無區(qū)別地對待原始的商務(wù)信息查詢模塊和增加新功能之后的商務(wù)信息查詢模塊,而且可能在將來還要在該信息查詢模塊中增加一些新的功能。

現(xiàn)使用代理模式設(shè)計(jì)并實(shí)現(xiàn)該收費(fèi)商務(wù)信息查詢系統(tǒng)。

實(shí)例分析及類圖:

商務(wù)信息查詢系統(tǒng)設(shè)計(jì)方案示意圖

商務(wù)信息查詢系統(tǒng)結(jié)構(gòu)圖

實(shí)例代碼

  • AccessValidator:身份驗(yàn)證類,業(yè)務(wù)類
  • Logger:日志記錄類,業(yè)務(wù)類
  • Searcher:抽象查詢類,充當(dāng)抽象主題角色
  • RealSearcher:具體查詢類,充當(dāng)真實(shí)主題角色
  • ProxySearcher:代理查詢類,充當(dāng)代理主題角色
  • Client:客戶端測試類

結(jié)果分析

  • 保護(hù)代理和智能引用代理
  • 在代理類ProxySearcher中實(shí)現(xiàn)對真實(shí)主題類的權(quán)限控制和引用計(jì)數(shù)

4. 遠(yuǎn)程代理

動機(jī)

  1. 客戶端程序可以訪問在遠(yuǎn)程主機(jī)上的對象,遠(yuǎn)程主機(jī)可能具有更好的計(jì)算性能與處理速度,可以快速地響應(yīng)并處理客戶端的請求
  2. 可以將網(wǎng)絡(luò)的細(xì)節(jié)隱藏起來,使得客戶端不必考慮網(wǎng)絡(luò)的存在
  3. 客戶端完全可以認(rèn)為被代理的遠(yuǎn)程業(yè)務(wù)對象是在本地而不是在遠(yuǎn)程,而遠(yuǎn)程代理對象承擔(dān)了大部分的網(wǎng)絡(luò)通信工作,并負(fù)責(zé)對遠(yuǎn)程業(yè)務(wù)方法的調(diào)用

結(jié)構(gòu)

5. 虛擬代理

動機(jī)

對于一些占用系統(tǒng)資源較多或者加載時(shí)間較長的對象,可以給這些對象提供一個(gè)虛擬代理

在真實(shí)對象創(chuàng)建成功之前虛擬代理扮演真實(shí)對象的替身,而當(dāng)真實(shí)對象創(chuàng)建之后,虛擬代理將用戶的請求轉(zhuǎn)發(fā)給真實(shí)對象

使用一個(gè)“虛假”的代理對象來代表真實(shí)對象,通過代理對象來間接引用真實(shí)對象,可以在一定程度上提高系統(tǒng)的性能

應(yīng)用

由于對象本身的復(fù)雜性或者網(wǎng)絡(luò)等原因?qū)е乱粋€(gè)對象需要較長的加載時(shí)間,此時(shí)可以用一個(gè)加載時(shí)間相對較短的代理對象來代表真實(shí)對象(結(jié)合多線程技術(shù))

一個(gè)對象的加載十分耗費(fèi)系統(tǒng)資源,讓那些占用大量內(nèi)存或處理起來非常復(fù)雜的對象推遲到使用它們的時(shí)候才創(chuàng)建,而在此之前用一個(gè)相對來說占用資源較少的代理對象來代表真實(shí)對象,再通過代理對象來引用真實(shí)對象(用時(shí)間換取空間)

6. Java動態(tài)代理

  • 動態(tài)代理(Dynamic Proxy)可以讓系統(tǒng)在運(yùn)行時(shí)根據(jù)實(shí)際需要來動態(tài)創(chuàng)建代理類,讓同一個(gè)代理類能夠代理多個(gè)不同的真實(shí)主題類而且可以代理不同的方法
  • Java語言提供了對動態(tài)代理的支持,Java語言實(shí)現(xiàn)動態(tài)代理時(shí)需要用到位于java.lang.reflect包中的一些類

Proxy類

  • public static Class< ? > getProxyClass(ClassLoader loader, Class... interfaces):該方法用于返回一個(gè)Class類型的代理類,在參數(shù)中需要提供類加載器并需要指定代理的接口數(shù)組(與真實(shí)主題類的接口列表一致)
  • public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):該方法用于返回一個(gè)動態(tài)創(chuàng)建的代理類的實(shí)例,方法中第一個(gè)參數(shù)loader表示代理類的類加載器,第二個(gè)參數(shù)interfaces表示代理類所實(shí)現(xiàn)的接口列表(與真實(shí)主題類的接口列表一致),第三個(gè)參數(shù)h表示所指派的調(diào)用處理程序類

InvocationHandler接口

  • InvocationHandler接口是代理處理程序類的實(shí)現(xiàn)接口,該接口作為代理實(shí)例的調(diào)用處理者的公共父類,每一個(gè)代理類的實(shí)例都可以提供一個(gè)相關(guān)的具體調(diào)用處理者(InvocationHandler接口的子類)
  • public Object invoke(Object proxy, Method method, Object[] args):該方法用于處理對代理類實(shí)例的方法調(diào)用并返回相應(yīng)的結(jié)果,當(dāng)一個(gè)代理實(shí)例中的業(yè)務(wù)方法被調(diào)用時(shí)將自動調(diào)用該方法。invoke()方法包含三個(gè)參數(shù),其中第一個(gè)參數(shù)proxy表示代理類的實(shí)例,第二個(gè)參數(shù)method表示需要代理的方法,第三個(gè)參數(shù)args表示代理方法的參數(shù)數(shù)組
  • 動態(tài)代理類需要在運(yùn)行時(shí)指定所代理真實(shí)主題類的接口,客戶端在調(diào)用動態(tài)代理對象的方法時(shí),調(diào)用請求會將請求自動轉(zhuǎn)發(fā)給InvocationHandler對象的invoke()方法,由invoke()方法來實(shí)現(xiàn)對請求的統(tǒng)一處理。

動態(tài)代理實(shí)例

“某軟件公司欲為公司OA系統(tǒng)數(shù)據(jù)訪問層DAO增加方法調(diào)用日志,記錄每一個(gè)方法被調(diào)用的時(shí)間和調(diào)用結(jié)果,現(xiàn)使用動態(tài)代理進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)。

實(shí)例代碼

  • AbstractUserDAO:抽象用戶DAO類,抽象主題角色
  • AbstractDocumentDAO:抽象文檔DAO類,抽象主題角色
  • UserDAO:用戶DAO類,具體主題角色
  • DocumentDAO:文檔DAO類,具體主題角色
  • DAOLogHandler:自定義請求處理程序類
  • Client:客戶端測試類

7. 代理模式的優(yōu)缺點(diǎn)與適用環(huán)境

模式優(yōu)點(diǎn)

  • 能夠協(xié)調(diào)調(diào)用者和被調(diào)用者,在一定程度上降低了系統(tǒng)的耦合度
  • 客戶端可以針對抽象主題角色進(jìn)行編程,增加和更換代理類無須修改源代碼,符合開閉原則,系統(tǒng)具有較好的靈活性和可擴(kuò)展性

模式優(yōu)點(diǎn)——逐個(gè)分析

  • 遠(yuǎn)程代理:可以將一些消耗資源較多的對象和操作移至性能更好的計(jì)算機(jī)上,提高了系統(tǒng)的整體運(yùn)行效率
  • 虛擬代理:通過一個(gè)消耗資源較少的對象來代表一個(gè)消耗資源較多的對象,可以在一定程度上節(jié)省系統(tǒng)的運(yùn)行開銷
  • 緩沖代理:為某一個(gè)操作的結(jié)果提供臨時(shí)的緩存存儲空間,以便在后續(xù)使用中能夠共享這些結(jié)果,優(yōu)化系統(tǒng)性能,縮短執(zhí)行時(shí)間
  • 保護(hù)代理:可以控制對一個(gè)對象的訪問權(quán)限,為不同用戶提供不同級別的使用權(quán)限

模式缺點(diǎn)

由于在客戶端和真實(shí)主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢(例如保護(hù)代理)

實(shí)現(xiàn)代理模式需要額外的工作,而且有些代理模式的實(shí)現(xiàn)過程較為復(fù)雜(例如遠(yuǎn)程代理)

模式適用環(huán)境

當(dāng)客戶端對象需要訪問遠(yuǎn)程主機(jī)中的對象時(shí)可以使用遠(yuǎn)程代理

當(dāng)需要用一個(gè)消耗資源較少的對象來代表一個(gè)消耗資源較多的對象,從而降低系統(tǒng)開銷、縮短運(yùn)行時(shí)間時(shí)可以使用虛擬代理

當(dāng)需要為某一個(gè)被頻繁訪問的操作結(jié)果提供一個(gè)臨時(shí)存儲空間,以供多個(gè)客戶端共享訪問這些結(jié)果時(shí)可以使用緩沖代理

當(dāng)需要控制對一個(gè)對象的訪問,為不同用戶提供不同級別的訪問權(quán)限時(shí)可以使用保護(hù)代理 

當(dāng)需要為一個(gè)對象的訪問(引用)提供一些額外的操作時(shí)可以使用智能引用代理

 

責(zé)任編輯:武曉燕 來源: 程序員千羽
相關(guān)推薦

2024-04-02 12:36:01

2021-05-11 08:54:59

建造者模式設(shè)計(jì)

2021-07-06 08:59:18

抽象工廠模式

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2021-08-01 07:19:16

語言OpenrestyNginx

2022-06-30 22:53:18

數(shù)據(jù)結(jié)構(gòu)算法

2021-12-04 22:05:02

Linux

2022-05-17 08:02:55

GoTryLock模式

2023-01-03 08:31:54

Spring讀取器配置

2021-07-05 22:11:38

MySQL體系架構(gòu)

2022-08-26 09:29:01

Kubernetes策略Master

2023-11-28 08:29:31

Rust內(nèi)存布局

2021-07-02 09:45:29

MySQL InnoDB數(shù)據(jù)

2022-08-23 08:00:59

磁盤性能網(wǎng)絡(luò)

2021-07-02 08:51:29

源碼參數(shù)Thread

2021-07-16 22:43:10

Go并發(fā)Golang

2021-09-28 08:59:30

復(fù)原IP地址

2022-04-12 08:30:52

回調(diào)函數(shù)代碼調(diào)試

2021-10-27 09:59:35

存儲
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號