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