搜尋
首頁Javajava教程Java代理模式詳細解析(圖文)

Java代理模式詳細解析(圖文)

Mar 22, 2017 am 10:19 AM
java代理模式

這篇文章主要為大家詳細介紹了Java代理模式的相關資料,具有一定的參考價值,有興趣的小夥伴們可以參考一下

代理模式是我們比較常用的設計模式之一。其中新想法是為了提供額外的處理或不同的操作而在實際物件與呼叫者之間插入一個代理物件。這些額外的操作通常需要與實際物件進行通信,代理模式一般涉及到的角色有:

抽象角色:聲明真實物件和代理物件的共同介面;

#代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理物件可以在執行真實物件操作時,附加其他的操作,相當於對真實物件進行封裝。

真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。

以下以傳送訊息為例來說明一個簡單的代理模式的基本實作:

首先明確目的:有一個訊息,需要把這個訊息發送出去,根據這個目的定義對應介面MessageHandler。需要的附加操作:假設需要驗證訊息的長度不能超過指定長度並且不能為空,並且我們需要統計相關資訊發送到次數,超過指定的次數我們需要輸出警報。我們透過代理模式來實現這個附加的操作。以下為對應的類別關係圖及範例程式碼。


//接口定义  
public interface MessageHandler {  
public void sendMessage(String msg);  
}  
//通过Email方式发送消息的实现类  
public class EmailMessage implements MessageHandler {  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
System.out.println(msg+" send!!");  
}  
}  
//消息处理的代理类  
public class MessageProxy implements MessageHandler {  
private static int count;  
private MessageHandler emailMsg;  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
if(checkMessage(msg))  
{  
if(emailMsg==null) emailMsg=new EmailMessage();  
count++;  
emailMsg.sendMessage(msg);  
System.out.println("Message sent:"+count);  
}  
}  
private boolean checkMessage(String msg) {  
return msg != null && msg.length() > 10;  
}  
}  
//调用类  
public class MainClass {  
private static void runProxy(MessageHandler handler)  
{  
handler.sendMessage("message for test");  
}  
/** 
 * @param args 
 */  
public static void main(String[] args) {  
// TODO Auto-generated method stub  
runProxy(new EmailMessage());  
System.out.println("++++++++++++++++Pjroxy++++++++++++++++++");  
runProxy(new MessageProxy());  
}  
}  
//输出  
message for test send!!  
++++++++++++++++Pjroxy++++++++++++++++++  
message for test send!!  
Message sent:1

 在範例中我們可以方便的在訊息傳送過程中加入各種需要的附加處理方式,也能方便的替換訊息的處理方式,如將透過Email發送訊息替換為透過簡訊發送訊息,而呼叫方不會有絲毫察覺!在任何你想要將一些額外操作分離到具體對象之外,特別是希望能夠很容易做出修改,或者想在具體對象的方法執行前插入一些額外操作的時候,代理就顯得十分有用!

動態代理

Java中動態代理機制的引入使得代理模式的想法更加完善與進步,它允許動態的創建代理並支援對動態的對所代理的方法進行呼叫。 Java動態代理類別位於Java.lang.reflect套件下,一般主要涉及以下兩個類別:

(1). Interface InvocationHandler:此介面中僅定義了一個方法Object:invoke(Object obj,Method method, Object[] args)。在實際使用時,第一個參數obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數數組。這個抽象方法在代理類別中動態實作。

(2).Proxy:該類即為動態代理類,作用類似於上例中的ProxySubject,其中主要包含以下內容:
Protected Proxy(InvocationHandler h):建構子,估計用於給內部的h賦值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):取得一個代理類,其中loader是類別裝載器,interfaces是真實類別所擁有的全部介面的陣列。

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):傳回代理類別的一個實例,傳回後的代理類別可以當作被代理類別使用(可使用被代理類別的在Subject介面中聲明過的方法)。

所謂Dynamic Proxy是這樣一種class:它是在運行時產生的class,在生成它時你必須提供一組interface給它,然後該class就宣稱它實現了這些interface 。你當然可以把該class的實例當作這些interface中的任何一個來用。當然啦,這個Dynamic Proxy其實就是一個Proxy,它不會為你做實質的工作,在產生它的實例時你必須提供一個handler,由它接手實際的工作。 下面我們透過動態代理重新實作上面發送訊息的範例!

 

在上面的範例基礎上,我們先加入一個透過簡訊來傳送訊息的處理類別:


public class SmsMessage implements MessageHandler {  
@Override  
public void sendMessage(String msg) {  
// TODO Auto-generated method stub  
System.out.println("SMS Message :" + msg+" sent !");  
}  
}  
//动态代理类  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
public class DynamicMessageProxy implements InvocationHandler {  
private static int count;  
private MessageHandler msgHandler;  
public DynamicMessageProxy(MessageHandler handler) {  
msgHandler = handler;  
}  
@Override  
public Object invoke(Object proxy, Method method, Object[] args)  
throws Throwable {  
// TODO Auto-generated method stub  
System.out.println("++++++++=============+++++++++");  
System.out.println("proxy:" + proxy.getClass());  
System.out.println("method:" + method);  
System.out.println("++++++++=============+++++++++");  
if (args != null && args.length == 1 && checkMessage((String) args[0])) {  
count++;  
System.out.println("Message sent:" + count);  
return method.invoke(msgHandler, args);  
}  
return null;  
}  
private boolean checkMessage(String msg) {  
return msg != null && msg.length() > 10;  
}  
}  
//下面是调用  
import java.lang.reflect.Proxy;  
public class MainClass {  
private static void runProxy(MessageHandler handler) {  
handler.sendMessage("message for test");  
}  
/** 
 * @param args 
 */  
public static void main(String[] args) {  
// TODO Auto-generated method stub  
// runProxy(new EmailMessage());  
// System.out.println("++++++++++++++++Proxy++++++++++++++++++");  
// runProxy(new MessageProxy());  
MessageHandler handler = new EmailMessage();  
runProxy(handler);  
MessageHandler proxy = (MessageHandler) Proxy.newProxyInstance(  
MessageHandler.class.getClassLoader(),  
new Class[] { MessageHandler.class }, new DynamicMessageProxy(  
handler));  
runProxy(proxy);  
System.out.println("++++++++++++++++++++++++++++++++++");  
// 短信方式  
handler = new SmsMessage();  
runProxy(handler);  
proxy = (MessageHandler) Proxy.newProxyInstance(MessageHandler.class  
.getClassLoader(), new Class[] { MessageHandler.class },  
new DynamicMessageProxy(handler));  
runProxy(proxy);  
}  
}  
//下面为以上方法的输出:  
message for test send!!  
++++++++=============+++++++++  
proxy:class $Proxy0  
method:public abstract void MessageHandler.sendMessage(java.lang.String)  
++++++++=============+++++++++  
Message sent:1  
message for test send!!  
++++++++++++++++++++++++++++++++++  
SMS Message :message for test sent !  
++++++++=============+++++++++  
proxy:class $Proxy0  
method:public abstract void MessageHandler.sendMessage(java.lang.String)  
++++++++=============+++++++++  
Message sent:2  
SMS Message :message for test sent !

 以上例子中,通过调用Proxy.newProxyInstance方法创建动态代理对象,该方法需要传入一个 类加载器、一组希望代理实现的接口列表、InvocationHandler 接口的一个具体实现。动态代理可以将所有调用重定向到调用处理器,通常我们会向该处理器传递一个时间对象的引用。invoke()方法中传递进来了代理对象,当你需要区分请求来源时这是非常有用的,例如你可以通过判断传入的方法名屏蔽掉某些方法的执行!动态代理机制并不是会很频繁使用的方法,它通常用来解决一些特定情况下的问题,因此不要盲目的为了使用而使用,要根据自己的实际需求来决定!

以上是Java代理模式詳細解析(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境