Java與設計模式-代理模式

來源:互聯網
上載者:User

Java與設計模式-代理模式

代理模式也稱為委託模式,屬於結構型設計模式,為其他對象提供一種代理,以控制對這個對象的訪問。這麼聽起來很難理解,生活中代理的例子也是很多的,畢業了要找房子,怎樣又快又好的找到自己心儀的房子,必須通過租房代理;想要買火車票,火車站太遠,我們可以選擇代理點進行購票。代碼模式的UML類圖如下:

應用情境:當無法或不想直接存取某個對象或訪問某個對象存在困難時可以通過一個代理對象來間接訪問,為了保證用戶端使用的透明性,委派物件與代理對象需要實現相同的介面。下面我們以“秋菊打官司”為例,講解一下代理模式。我們都知道在打官司時都要請一個律師,這個律師就可以認為是我們的代理,我們通過他進行某些操作。

首先抽象類別,打官司:

package com.proxy.demo;public abstract class Lawsuit {/** * 抽象類別 */abstract void lawsuit();}

非常簡單,就一個抽象方法,下面實現秋菊類,也就是真實類,覆寫實現這個抽象方法:

package com.proxy.demo;public class QiuJu extends Lawsuit {/** * 真實類 */@Overridevoid lawsuit() {System.out.println("我是秋菊,我要打官司!");}}

下面是代理類:

package com.proxy.demo;public class ProxySubject {/** * 代理類 */QiuJu qiuJu=null;public ProxySubject(QiuJu qiuJu) {//通過構造方法引入秋菊對象this.qiuJu=qiuJu;}public void lawsuit(){qiuJu.lawsuit();//代理幫秋菊打官司}}

代理類其實什麼都沒做,只是調用了真實類的方法。下面測試類別:

package com.proxy.demo;public class TestClass {public static void main(String[] args) {QiuJu qiuJu=new QiuJu();ProxySubject proxySubject=new ProxySubject(qiuJu);proxySubject.lawsuit();//通過代理調用方法}}

運行測試方法:

我們可以看出,代理調用了真實類的方法,順利實現了。這裡順便插一下,調整控制台字型大小的方法:

開啟window - preferences-- general - appearance - colors and fonts --debug - console font 就可以調節了

代理模式是十分常用的方法,細心的朋友會發現,我們上一節文章《策略模式》就用到了代理模式。代理模式大致可以分為兩個部分,一是靜態代理,二是動態代理。上面講的就是靜態代理,代理者的代碼由程式員自己或者通過一些自動化工具產生固定的代碼再對其進行編譯,也就是說,在我們的代碼運行之前代理類的class編譯檔案就已經存在;而動態代碼則是通過反射機制動態地組建代理程式者的對象,代理誰將會在執行階段決定。Java也給我們提供了一個便捷的動態代理介面InvocationHandler,實現這個介面需要重寫其調用方法invoke。也就是說,首先我們要完善這個動態代理類:

package com.proxy.demo;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class DynamicProxy implements InvocationHandler {Object object=null;public DynamicProxy(Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object  result=method.invoke(object, args);return result;}}

Interface InvocationHandler:該介面中僅定義了一個方法Object:invoke(Object obj,Method method, J2EEjava語言JDK1.4APIjavalangObject.html">Object[] args)。在實際使用時,第一個參數obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數數組。這個抽象方法在代理類中動態實現。
原來在代理類中處理的事情交給InvocationHandler來處理,不再關心到底代理誰。

下面修改測試類別:

package com.proxy.demo;import java.lang.reflect.Proxy;public class TestClass {public static void main(String[] args) {/* * QiuJu qiuJu=new QiuJu(); ProxySubject proxySubject=new * ProxySubject(qiuJu); proxySubject.lawsuit();//通過代理調用方法 */Lawsuit lawsuit = new QiuJu();DynamicProxy dynamicProxy = new DynamicProxy(lawsuit);ClassLoader loader = lawsuit.getClass().getClassLoader();// 擷取被代理類的ClassLoader// 動態構造一個代理律師對象Lawsuit lawyer = (Lawsuit) Proxy.newProxyInstance(loader, new Class[] { Lawsuit.class }, dynamicProxy);lawyer.lawsuit();}}


注意,由於動態代理需要,此時的Lawsuit變成了介面,QiuJu類變成實現介面。

運行執行個體,和靜態代理一樣的結果:

可以看出,動態代理類可以代理N個被代理類,其實質對代理類和被代理類進行解耦,使兩者沒有直接的解耦關係,使用時更靈活。而靜態代理更符合物件導向的思想,在開發時可以根據需要實現代理。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.