摘要:三二模式分析代理模式的示意圖結(jié)構(gòu)比較簡單一般可以簡化如下圖所示。五總結(jié)在代理模式中,要求給某一個(gè)對象提供一個(gè)代理,并由代理對象控制對原對象的訪問,其英文為是一種結(jié)構(gòu)型模式。
一、寫在前面
代理模式是常用的結(jié)構(gòu)型設(shè)計(jì)模式之一、當(dāng)我們直接訪問某些對象存在問題時(shí)可以通過代理模式來間接訪問,為了保證客戶端使用的透明性、所訪問的真實(shí)對象和代理對象都必須實(shí)現(xiàn)同一個(gè)接口。
二、代理模式動(dòng)機(jī)與定義某人要找對象(大部分是程序員),但是由于某些原因(996)不能直接去找。
于是就委托一個(gè)中介機(jī)構(gòu)去幫自己完成找女朋友的過程,如婚姻中介所、某某社交軟件等。
在這里婚姻介紹所或者某某社交軟件就是一個(gè)代理,幫你找美女。
在我們生活中代理無處不在、比如房屋中介、職業(yè)中介(某某招聘網(wǎng))等它們充當(dāng)?shù)亩际且粋€(gè)代理角色。
所謂的代理就是一個(gè)人或者一個(gè)機(jī)構(gòu)代表另一個(gè)人或者機(jī)構(gòu)采取行動(dòng)。
二.一 模式動(dòng)機(jī)在某些情況下,一個(gè)客戶不想或者不能直接應(yīng)用另一個(gè)對象,可以通過一個(gè)稱之為‘代理’的第三者來實(shí)現(xiàn)間接的引用。
代理對象在客戶和目標(biāo)對象之間起到一個(gè)中介的作用,并且可以通過代理對象去掉某些客戶不能看到的內(nèi)容或者服務(wù),同時(shí)也可以添加客戶需要的額外服務(wù)。
二.二 模式的定義代理模式(Proxy Patten)定義:給某一個(gè)對象提供一個(gè)代理,并由代理對象控制對原對象的引用。
代理對象英文名稱叫做 Peoxy 或者 Surrogate 他是一種對象結(jié)構(gòu)模式。
三、代理模式結(jié)構(gòu)與分析代理模式結(jié)構(gòu)比較簡單、其核心就是一個(gè)代理類,下面我們來分析下其模式結(jié)構(gòu)
三.一 模式結(jié)構(gòu)代理模式UML圖
代理模式包含以下三個(gè)角色
Subject(抽象主題角色)
抽象主題角色申明了真實(shí)主題和代理主題的共同接口、這樣以來任何使用真實(shí)主題的地方可以都使用代理主題、客戶端需要針對抽象主題角色來編程
Proxy(代理主題角色)
代理主題角色包含了對真實(shí)主題的引用,從而可以在任何時(shí)候操作真實(shí)主題角色。
RealSubject(真實(shí)主題角色)
真實(shí)主題角色定義了代理主題角色所代表的具體對象,真實(shí)主題角色中實(shí)現(xiàn)了真實(shí)的業(yè)務(wù)操作,客戶端可以通過代理主題角色來間接的調(diào)用真實(shí)主題角色中定義的方法。
代理模式的示意圖結(jié)構(gòu)比較簡單、一般可以簡化如下圖所示。
但是在現(xiàn)實(shí)中要復(fù)雜的多。
典型的代理類代碼如下:
public class Proxy implements Subject { private RealSubject realSubject = new RealSubject(); public void preRequest() { System.out.println("---pre---"); } public void request() { preRequest(); realSubject.request(); postRequest(); } public void postRequest() { System.out.println("----post-----"); } }
在真實(shí)應(yīng)用中,代理類的實(shí)現(xiàn)好比著復(fù)雜的多,它需要一套自己的方式去訪問真實(shí)對象,以便作為真實(shí)對象的代理。
四、代理模式的實(shí)例代理模式在我應(yīng)用開發(fā)中一般就分為靜態(tài)代理和動(dòng)態(tài)代理兩類。
下面我們來一個(gè)例子來具體的理解下代理模式
下面我們以我們最熟悉的Spring AOP 處理事務(wù)的方式來實(shí)現(xiàn),廢話不多說直接上代碼吧!
抽象角色
public interface TrancationSubject { void request(); }
具體角色
public class TrancationRealSubject implements TrancationSubject { public void request() { System.err.println("---執(zhí)行事務(wù)方法---"); }
代理角色
public class TrancationProxy implements TrancationSubject { private TrancationRealSubject realSubject; public TrancationProxy(TrancationRealSubject realSubject) { super(); this.realSubject = realSubject; } public void preRequest() { System.out.println("---open trancation---"); } public void request() { preRequest(); realSubject.request(); postRequest(); } public void postRequest() { System.out.println("----commit/rollback-----"); } }
client端
public class Client { public static void main(String[] args) { TrancationProxy proxy = new TrancationProxy(new TrancationRealSubject()); proxy.request(); } }
執(zhí)行結(jié)果
---open trancation--- ---執(zhí)行事務(wù)方法--- ----commit/rollback
上述靜態(tài)代理其優(yōu)點(diǎn)就不多說了,繼承了代理模式的優(yōu)點(diǎn),但是其缺點(diǎn)就不得不嘮叨下了。
缺點(diǎn):
1)代理類和委托類實(shí)現(xiàn)了相同的接口,代理類通過委托類實(shí)現(xiàn)了相同的方法。這樣就出現(xiàn)了大量的代碼重復(fù)。如果接口增加一個(gè)方法,除了所有實(shí)現(xiàn)類需要實(shí)現(xiàn)這個(gè)方法外,所有代理類也需要實(shí)現(xiàn)此方法。增加了代碼維護(hù)的復(fù)雜度。
2)代理對象只服務(wù)于一種類型的對象,如果要服務(wù)多類型的對象。勢必要為每一種對象都進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時(shí)就無法勝任了。
由于這兩種致命的缺點(diǎn)到這在真實(shí)的應(yīng)用環(huán)境中很難看到靜態(tài)代理的使用。
下面我們來說說其高配版。
四.二 動(dòng)態(tài)代理動(dòng)態(tài)代理是一種高級(jí)代理模式,最典型的引用場景就是Spring AOP 。
Java動(dòng)態(tài)到了實(shí)現(xiàn)相關(guān)包主要位于java.lang.reflect包下面主要涉及兩個(gè)類
(1) InvocationHandler 接口,它是代理實(shí)例的調(diào)用處理程序?qū)崿F(xiàn)的接口,該結(jié)構(gòu)定義了如下方法。
Object invoke(Object proxy,Method method,Object[] args) throws Throwable
在代理實(shí)例上處理方法調(diào)用并返回結(jié)果。在與方法關(guān)聯(lián)的代理實(shí)例上調(diào)用方法時(shí),將在調(diào)用處理程序上調(diào)用此方法。
參數(shù):
proxy - 在其上調(diào)用方法的代理實(shí)例
method - 對應(yīng)于在代理實(shí)例上調(diào)用的接口方法的 Method 實(shí)例。 Method 對象的聲明類將是在其中聲明方法的接口,該接口可以是代理類賴以繼承方法的代理接口的超接口。
args - 包含傳入代理實(shí)例上方法調(diào)用的參數(shù)值的對象數(shù)組,如果接口方法不使用參數(shù),則為 null?;绢愋偷膮?shù)被包裝在適當(dāng)基本包裝器類(如 java.lang.Integer 或 java.lang.Boolean)的實(shí)例中。
(2) Proxy 類,該類即為動(dòng)態(tài)代理類,最常用的方法為
newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
返回一個(gè)指定接口的代理類實(shí)例,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序。
參數(shù):
loader - 定義代理類的類加載器
interfaces - 代理類要實(shí)現(xiàn)的接口列表
h - 指派方法調(diào)用的調(diào)用處理程序
對上面動(dòng)態(tài)代理一些主要方法做下了解,下面我們該早上面代理類。
public class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy(Object obj) { super(); this.obj = obj; } public void preRequest() { System.out.println("---open trancation--- "); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { preRequest(); Object invoke = method.invoke(obj, args); postRequest(); return invoke; } public void postRequest() { System.out.println("----commit/rollback-----"); } }
client
public class Client { public static void main(String[] args) { DynamicProxy invocationHandler = new DynamicProxy(new TrancationRealSubject()); TrancationSubject newProxyInstance = (TrancationSubject) Proxy.newProxyInstance( TrancationSubject.class.getClassLoader(), new Class[] { TrancationSubject.class }, invocationHandler); newProxyInstance.request(); } }
在這執(zhí)行結(jié)果就不貼了。
動(dòng)態(tài)代理與靜態(tài)代理相比較,最大的好處是接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個(gè)集中的方法中處理(InvocationHandler.invoke)。
這樣,在接口方法數(shù)量比較多的時(shí)候,我們可以進(jìn)行靈活處理,而不需要像靜態(tài)代理那樣每一個(gè)方法進(jìn)行中轉(zhuǎn)。而且動(dòng)態(tài)代理的應(yīng)用使我們的類職責(zé)更加單一,復(fù)用性更強(qiáng)。
在代理模式中,要求給某一個(gè)對象提供一個(gè)代理,并由代理對象控制對原對象的訪問,其英文為proxy 是一種結(jié)構(gòu)型模式。
代理模式包含三種角色,抽象主題角色、代理主題角色、真實(shí)主題角色。
代理模式的優(yōu)點(diǎn)在于協(xié)調(diào)調(diào)用者和被調(diào)用者,在一定的程度上降低了系統(tǒng)的耦合性。其缺點(diǎn)在調(diào)用者和被調(diào)用者中間增加了代理層,因此有些類型的代理模式可能會(huì)造成請求處理速度變慢,并且代理模式需要額外的工作,有些代理模式的實(shí)現(xiàn)非常復(fù)雜。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74864.html
摘要:下面總結(jié)了它倆的異同相同點(diǎn)都需要實(shí)現(xiàn)同一個(gè)接口或者繼承同一個(gè)抽象類,并且代理角色和裝飾角色都持有被代理角色和構(gòu)件角色的引用。 寫完上一篇之后有小伙伴問我有沒有寫過代理模式,想看看我的理解。原本我的設(shè)計(jì)模式系列是按照創(chuàng)建型-行為型-結(jié)構(gòu)型的順序?qū)懴氯サ?,既然小伙伴誠心誠意了,我就大發(fā)慈悲的穿插一篇代理模式。開玩笑,題外話。 說起代理模式,就不由得想起經(jīng)紀(jì)人,說起經(jīng)紀(jì)人,就想起了...對,...
摘要:簡介代理模式和裝飾者模式是兩種常見的設(shè)計(jì)模式。這里通過構(gòu)造函數(shù)的參數(shù)將被代理對象傳入到代理中,也可以通過其它方式,如提供一個(gè)方法。下面是的代碼輸出首先依然是先創(chuàng)建一個(gè)需要被代理的對象,然后把它傳入到的構(gòu)造函數(shù)中。 簡介 代理模式和裝飾者模式是兩種常見的設(shè)計(jì)模式。代理模式是為其它對象提供一種代理以控制對這個(gè)對象的訪問。在某些情況下,一個(gè)對象不適合或者不能直接引用另一個(gè)對象,而代理對象可以...
摘要:代理設(shè)計(jì)模式代理模式為其他對象提供一種代理以控制對這個(gè)對象的訪問。代理模式是常見的設(shè)計(jì)模式之一是指不直接調(diào)用實(shí)際的對象,而是通過代理對象,來間接的調(diào)用實(shí)際的對象。對象類定義了代理對象所代表的目標(biāo)對象。 代理設(shè)計(jì)模式 代理模式:為其他對象提供一種代理以控制對這個(gè)對象的訪問。代理模式是常見的設(shè)計(jì)模式之一,是指不直接調(diào)用實(shí)際的對象,而是通過代理對象,來間接的調(diào)用實(shí)際的對象。為什么要采用這種間...
摘要:代理模式原文地址更多設(shè)計(jì)模式系列教程更多免費(fèi)教程博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。代理模式優(yōu)缺點(diǎn)代理模式有高度解耦對象保護(hù)易修改等優(yōu)點(diǎn)。 代理模式·原文地址 更多《設(shè)計(jì)模式系列教程》 更多免費(fèi)教程 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(_靠這吃飯_)和python(_純粹喜歡_)...
閱讀 1459·2021-11-08 13:14
閱讀 816·2021-09-23 11:31
閱讀 1118·2021-07-29 13:48
閱讀 2858·2019-08-29 12:29
閱讀 3440·2019-08-29 11:24
閱讀 1963·2019-08-26 12:02
閱讀 3809·2019-08-26 10:34
閱讀 3529·2019-08-23 17:07