日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

代理模式--结构型

發(fā)布時(shí)間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 代理模式--结构型 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  代理模式是常用的Java 設(shè)計(jì)模式,它的特征是代理類(lèi)與委托類(lèi)有同樣的接口,代理類(lèi)主要負(fù)責(zé)為委托類(lèi)預(yù)處理消息、過(guò)濾消息、把消息轉(zhuǎn)發(fā)給委托類(lèi),以及事后處理消息等。代理類(lèi)與委托類(lèi)之間通常會(huì)存在關(guān)聯(lián)關(guān)系,一個(gè)代理類(lèi)的對(duì)象與一個(gè)委托類(lèi)的對(duì)象關(guān)聯(lián),代理類(lèi)的對(duì)象本身并不真正實(shí)現(xiàn)服務(wù),而是通過(guò)調(diào)用委托類(lèi)的對(duì)象的相關(guān)方法,來(lái)提供特定的服務(wù)。?

按照代理類(lèi)的創(chuàng)建時(shí)期,代理類(lèi)可分為兩種。?
  靜態(tài)代理類(lèi):?
    由程序員創(chuàng)建或由特定工具自動(dòng)生成源代碼,再對(duì)其編譯。在程序運(yùn)行前,代理類(lèi)的.class文件就已經(jīng)存在了。?
  動(dòng)態(tài)代理類(lèi):在程序運(yùn)行時(shí),運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成。

一、靜態(tài)代理

代理模式涉及的角色:
1:抽象主題角色.聲明了代理主題和真實(shí)主題的公共接口,使任何需要真實(shí)主題的地方都能用代理主題代替.

2:代理主題角色.含有真實(shí)主題的引用,從而可以在任何時(shí)候操作真實(shí)主題,代理主題功過(guò)提供和真實(shí)主題相同的接口,使它可以隨時(shí)代替真實(shí)主題.代理主題通過(guò)持有真實(shí)主題的引用,不但可以控制真實(shí)主題的創(chuàng)建或刪除,可以在真實(shí)主題被調(diào)用前進(jìn)行攔截,或在調(diào)用后進(jìn)行某些操作.

3:真實(shí)代理對(duì)象.定義了代理角色所代表的具體對(duì)象.

下面是代理模式的實(shí)現(xiàn)類(lèi)圖: ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

?結(jié)構(gòu)

Uml圖:

代理模式也叫做委托模式,它是一項(xiàng)基本設(shè)計(jì)技巧。許多其他的模式,如狀態(tài)模式、策略模式、訪問(wèn)者模式本質(zhì)上是在更特殊的場(chǎng)合采用了委托模式,而且在日常的應(yīng)用中,代理模式可以提供非常好的訪問(wèn)控制。在一些著名開(kāi)源軟件中也經(jīng)常見(jiàn)到它的身影,如Struts2的Form元素映射就采用了代理模式(準(zhǔn)確地說(shuō)是動(dòng)態(tài)代理模式)。我們先看一下類(lèi)圖中的三個(gè)角色的定義:
● Subject抽象主題角色
抽象主題類(lèi)可以是抽象類(lèi)也可以是接口,是一個(gè)最普通的業(yè)務(wù)類(lèi)型定義,無(wú)特殊要求。
● RealSubject具體主題角色
也叫做被委托角色、被代理角色。它才是冤大頭,是業(yè)務(wù)邏輯的具體執(zhí)行者。
● Proxy代理主題角色
也叫做委托類(lèi)、代理類(lèi)。它負(fù)責(zé)對(duì)真實(shí)角色的應(yīng)用,把所有抽象主題類(lèi)定義的方法限制委托給真實(shí)主題角色實(shí)現(xiàn),并且在真實(shí)主題角色處理完畢前后做預(yù)處理和善后處理工作。

示例:

代理,指的就是一個(gè)角色代表另一個(gè)角色采取行動(dòng),就象生活中,一個(gè)紅酒廠商,是不會(huì)直接把紅酒零售客戶的,都是通過(guò)代理來(lái)完成他的銷(xiāo)售業(yè)務(wù)的.而客戶,也不用為了喝紅酒而到處找工廠,他只要找到廠商在當(dāng)?shù)氐拇砭托辛?具體紅酒工廠在那里,客戶不用關(guān)心,代理會(huì)幫他處理。根據(jù)上圖的關(guān)系,我們可以用客戶買(mǎi)紅酒來(lái)模擬代理模式的實(shí)現(xiàn), 紅酒代理商和紅酒廠商都有銷(xiāo)售紅酒的只能,我們可以為他們定義一個(gè)共同的抽象主題角色

package com.dxz.pattern.proxy;/*** 抽象主題角色,定義了真實(shí)角色和代理角色的公共接口*/ public interface SellInterface {public Object sell(); }

接著,我們定義真實(shí)主題角色(這里就是紅酒工廠),它必須實(shí)現(xiàn)了SellInterface接口的.

package com.dxz.pattern.proxy;/*** 真實(shí)主題角色,這里指紅酒工廠角色,它實(shí)現(xiàn)了SellInterface接口*/ public class RedWineFactory implements SellInterface {public Object sell() {System.out.println("真實(shí)主題角色RedWineFactory 被調(diào)用了");return new Object();} }

?

下面是代理主題角色(這里指紅酒代理商),同樣,代理主題也必須實(shí)現(xiàn)SellInterface接口.

package com.dxz.pattern.proxy;/*** 代理主題角色,這里指紅酒代理商.它除了也要實(shí)現(xiàn)了sellInterface接口外,還持有紅酒廠商RedWineFactory* 對(duì)象的引用,從而使它能在調(diào)用真實(shí)主題前后做一些必要處理.*/public class RedWineProxy implements SellInterface {// 持有一個(gè)RedWineFactory對(duì)象的引用private RedWineFactory redWineFactory;public RedWineProxy(RedWineFactory redWineFactory) {this.redWineFactory = redWineFactory;}// 銷(xiāo)售總量private static int sell_count = 0;public Object sell() {if (checkUser()) {// 在通過(guò)代理主題角色,我們可以在真實(shí)主題角色被調(diào)用前做一些諸如權(quán)限判斷的事情Object obj = redWineFactory.sell();sell_count++;// 同樣,在調(diào)用后我們也可以執(zhí)行一些額外的動(dòng)作.return obj;} else {throw new RuntimeException();}}protected boolean checkUser() {// do somethingreturn true;}// 接下來(lái)看看調(diào)用代理對(duì)象的代碼:public static void main(String[] args) {SellInterface sell = new RedWineProxy(new RedWineFactory());sell.sell();} }

從類(lèi)圖我們可以看出,客戶端本來(lái)可以直接和目標(biāo)對(duì)象打交道,代理中間加了一個(gè)間接層,他們實(shí)現(xiàn)的功能是一樣的,也沒(méi)有改變參數(shù)。相信大家對(duì)上面的類(lèi)圖和代碼很熟悉,跟我們平時(shí)看別人的博文一樣,沒(méi)有任何區(qū)別,下面我們看一下靜態(tài)代理的優(yōu)缺點(diǎn)。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1、直觀感受,靜態(tài)代理是實(shí)實(shí)在在的存在的,我們自己寫(xiě)的。

2、在編譯期加入,提前就指定好了誰(shuí)調(diào)用誰(shuí),效率高。

缺點(diǎn)

同樣,它的優(yōu)點(diǎn)也成了它致命的缺點(diǎn)。

1、靜態(tài)代理很麻煩,需要大量的代理類(lèi)

? ? ?當(dāng)我們有多個(gè)目標(biāo)對(duì)象需要代理時(shí),我就需要建立多個(gè)代理類(lèi),改變?cè)械拇a,改的多了就很有可能出問(wèn)題,必須要重新測(cè)試。

2、重復(fù)的代碼會(huì)出現(xiàn)在各個(gè)角落里,違背了一個(gè)原則:重復(fù)不是好味道,我們應(yīng)該杜絕一次次的重復(fù)。

3、在編譯期加入,系統(tǒng)的靈活性差

? ? ? ?我們可以看到代理類(lèi)的每個(gè)方法中,都有記錄日志,執(zhí)行成功或失敗的代碼,每個(gè)方法都重復(fù)了一遍,如果我們需要修改的話,并沒(méi)有比不用靜態(tài)代理時(shí)減少修改的地方,只是不用修改目標(biāo)類(lèi)。動(dòng)態(tài)代理很好的為我們解決了這個(gè)問(wèn)題,下面我們看一下動(dòng)態(tài)代理。

?

二、java對(duì)代理模式的支持 ---動(dòng)態(tài)代理
上面的代理,我們強(qiáng)迫代理類(lèi)RedWineProxy實(shí)現(xiàn)了抽象接口SellInterface.這導(dǎo)致我們的代理類(lèi)無(wú)法通用于其他接口,所以不得不為每一個(gè)接口實(shí)現(xiàn)一個(gè)代理類(lèi).幸好,java為代理模式提供了支持.
java主要是通過(guò)Proxy類(lèi)和InvocationHandler接口來(lái)給實(shí)現(xiàn)對(duì)代理模式的支持的.


下面用java的代理機(jī)制來(lái)實(shí)現(xiàn)上面的例子

package com.dxz.pattern.proxy;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;import java.lang.reflect.Proxy;/*** 代理類(lèi)一定要實(shí)現(xiàn)了InvocationHandler接口*/ public class ProxyHandler implements InvocationHandler {private Object proxy_obj;ProxyHandler(Object obj) {this.proxy_obj = obj;}public static Object factory(Object obj) {Class cls = obj.getClass();// 通過(guò)Proxy類(lèi)的newProxyInstance方法來(lái)返回代理對(duì)象return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), new ProxyHandler(obj));}/*** 實(shí)現(xiàn)InvocationHandler接口的invoke*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("函數(shù)調(diào)用前被攔截了: " + method);if (args != null) {// 打印參數(shù)列表System.out.println("方法有 " + args.length + " 個(gè)參數(shù)");for (int i = 0; i < args.length; i++) {System.out.println(args[i]);}}// 利用反射機(jī)制動(dòng)態(tài)調(diào)用原對(duì)象的方法Object mo = method.invoke(proxy_obj, args);System.out.println("函數(shù)調(diào)用后進(jìn)行處理 : " + method);return mo;} }

調(diào)用方法:

package com.dxz.pattern.proxy;public class Client {// 測(cè)試代碼public static void main(String agr[]) {SellInterface si = (SellInterface) ProxyHandler.factory(new RedWineFactory());si.sell();}}

執(zhí)行結(jié)果:

函數(shù)調(diào)用前被攔截了: public abstract java.lang.Object com.dxz.pattern.proxy.SellInterface.sell() 真實(shí)主題角色RedWineFactory 被調(diào)用了 函數(shù)調(diào)用后進(jìn)行處理 : public abstract java.lang.Object com.dxz.pattern.proxy.SellInterface.sell()

通過(guò)上面的代碼可以看出,代理主題ProxyHandler類(lèi)并沒(méi)有實(shí)現(xiàn)我們定義的SellInterface接口,而是實(shí)現(xiàn)了java的InvocationHandler接口,這樣就把代理主題角色和我們的業(yè)務(wù)代碼分離開(kāi)來(lái),使代理對(duì)象能通用于其他接口。

動(dòng)態(tài)代理優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1、一個(gè)動(dòng)態(tài)代理類(lèi)更加簡(jiǎn)單了,可以解決創(chuàng)建多個(gè)靜態(tài)代理的麻煩,避免不斷的重復(fù)多余的代碼

2、調(diào)用目標(biāo)代碼時(shí),會(huì)在方法“運(yùn)行時(shí)”動(dòng)態(tài)的加入,決定你是什么類(lèi)型,才調(diào)誰(shuí),靈活

缺點(diǎn):

1、系統(tǒng)靈活了,但是相比而言,效率降低了,比靜態(tài)代理慢一點(diǎn)

2、動(dòng)態(tài)代理比靜態(tài)代理在代碼的可讀性上差了一點(diǎn),不太容易理解

3、JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類(lèi)進(jìn)行代理

三、InvocationHandler

詳細(xì)見(jiàn):JDK的動(dòng)態(tài)代理深入解析(Proxy,InvocationHandler)(轉(zhuǎn))

?

四、代理模式分類(lèi):

代理模式根據(jù)其目的和實(shí)現(xiàn)方式不同可分為很多種類(lèi),其中常用的幾種代理模式簡(jiǎn)要說(shuō)明如下:

遠(yuǎn)程代理(Remote Proxy)

給一個(gè)位于不同的地址空間的對(duì)象提供一個(gè)本地的代理對(duì)象,這個(gè)不同的地址空間可以是在同一臺(tái)主機(jī)中,也可是在另一臺(tái)主機(jī)中,遠(yuǎn)程代理又稱(chēng)為大使(Ambassador)。

虛擬代理(Virtual Proxy)

如果需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,先創(chuàng)建一個(gè)消耗相對(duì)較小的對(duì)象來(lái)表示,真實(shí)對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建。

保護(hù)代理(Protect Proxy)

控制對(duì)一個(gè)對(duì)象的訪問(wèn),可以給不同的用戶提供不同級(jí)別的使用權(quán)限。

緩沖代理(Cache Proxy)

為某一個(gè)目標(biāo)操作的結(jié)果提供臨時(shí)的存儲(chǔ)空間,以便多個(gè)客戶端可以共享這些結(jié)果。

智能引用代理(Smart Reference Proxy)

當(dāng)一個(gè)對(duì)象被引用時(shí),提供一些額外的操作,例如將對(duì)象被調(diào)用的次數(shù)記錄下來(lái)等。

?

五、與其他相關(guān)模式

1)適配器模式Adapter?:適配器Adapter 為它所適配的對(duì)象提供了一個(gè)不同的接口。相反,代理提供了與它的實(shí)體相同的接口。然而,用于訪問(wèn)保護(hù)的代理可能會(huì)拒絕執(zhí)行實(shí)體會(huì)執(zhí)行的操作,因此,它的接口實(shí)際上可能只是實(shí)體接口的一個(gè)子集。

2) 裝飾器模式Decorator:盡管Decorator的實(shí)現(xiàn)部分與代理相似,但Decorator的目的不一樣。Decorator為對(duì)象添加一個(gè)或多個(gè)功能,而代理則控制對(duì)對(duì)象的訪問(wèn)。

總結(jié)

代理模式在很多情況下都非常有用,特別是你想強(qiáng)行控制一個(gè)對(duì)象的時(shí)候,比如:延遲加載,監(jiān)視狀態(tài)變更的方法等等

1、“增加一層間接層”是軟件系統(tǒng)中對(duì)許多負(fù)責(zé)問(wèn)題的一種常見(jiàn)解決方法。在面向?qū)ο笙到y(tǒng)中,直接使用某些對(duì)象會(huì)帶來(lái)很多問(wèn)題,作為間接層的proxy對(duì)象便是解決這一問(wèn)題的常用手段。

2、具體proxy設(shè)計(jì)模式的實(shí)現(xiàn)方法、實(shí)現(xiàn)粒度都相差很大,有些可能對(duì)單個(gè)對(duì)象作細(xì)粒度的控制,有些可能對(duì)組件模塊提供抽象代理層,在架構(gòu)層次對(duì)對(duì)象作proxy。

3、proxy并不一定要求保持接口的一致性,只要能夠?qū)崿F(xiàn)間接控制,有時(shí)候損及一些透明性是可以接受的。

代理模式能夠協(xié)調(diào)調(diào)用者和被調(diào)用者,在一定程度上降低了系統(tǒng)的耦合度。


代理模式的優(yōu)缺點(diǎn)

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

  • ?職責(zé)清晰

    真實(shí)的角色就是實(shí)現(xiàn)實(shí)際的業(yè)務(wù)邏輯,不用關(guān)心其他非本職責(zé)的事務(wù),通過(guò)后期的代理完成一件事務(wù),附帶的結(jié)果就是編程簡(jiǎn)潔清晰。

  • ?高擴(kuò)展性

    具體主題角色是隨時(shí)都會(huì)發(fā)生變化的,只要它實(shí)現(xiàn)了接口,甭管它如何變化,都逃不脫如來(lái)佛的手掌(接口),那我們的代理類(lèi)完全就可以在不做任何修改的情況下使用。

  • ?智能化

    這在我們以上的講解中還沒(méi)有體現(xiàn)出來(lái),不過(guò)在我們以下的動(dòng)態(tài)代理章節(jié)中你就會(huì)看到代理的智能化有興趣的讀者也可以看看Struts是如何把表單元素映射到對(duì)象上的。

?

代理模式的缺點(diǎn)

  • 由于在客戶端和真實(shí)主題之間增加了代理對(duì)象,因此有些類(lèi)型的代理模式可能會(huì)造成請(qǐng)求的處理速度變慢。
  • 實(shí)現(xiàn)代理模式需要額外的工作,有些代理模式的實(shí)現(xiàn)非常復(fù)雜。

轉(zhuǎn)載于:https://www.cnblogs.com/duanxz/archive/2012/05/25/2517486.html

總結(jié)

以上是生活随笔為你收集整理的代理模式--结构型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。