談談JAVA的代理模式認識 一——為什麼使用代理模式
一、中介隔離作用
代理模式,第一次接觸它,是在學習.Net的時候看的一本書,叫做《大話設計模式》,至今已快三年了。相信看過這本書的同學們,都記得書中的代理模式,就是為他人做嫁衣裳的故事。好,我們迴歸代理模式的定義:為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用, 其特徵是代理類與委託類有同樣的介面,。代理模式是常用的java設計模式。
表現形式如下:
以上一張圖就是當初對代理模式的認識。
二、開閉原則,增加功能,
現在有了進一步的認識。代理類不僅僅是一個隔離客戶端和委託類的中介。我們還可以藉助代理來在增加一些功能,而不需要修改原有程式碼,嚴重的複合開閉原則哦。
代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本身並不真正實現服務,而是通過呼叫委託類的物件的相關方法,來提供特定的服務。
就是這樣,真正的業務功能還是有委託類來實現,但是在實現業務類之前的一些公共服務。例如在專案開發中我們沒有加入緩衝,日誌這些功能,後期想加入,我們就可以使用代理來實現,而沒有必要開啟已經封裝好的委託類。
三、代理的分類
根據以上對代理的理解,對於代理的具體實現,我們有不同的方式,如果按照代理的建立時期,代理類可以分為兩種。:靜態代理、動態代理。
靜態代理:由程式設計師建立或特定工具自動生成原始碼,再對其編譯。在程式執行前,代理類的.class檔案就已經存在了。
動態代理:在程式執行時,運用反射機制動態建立而程。
1、靜態代理
那我們先來看一下靜態代理。只需要三步即可實現。首先,我們需要定義業務介面,業務介面實現類,然後定義代理類,且實現業務介面;最後寫一個Client來呼叫。
第一:需要定義業務介面,業務介面實現類
<span style="font-family:KaiTi_GB2312;font-size:18px;"> /** * 定義一個業務介面 * @author Cassie */ public interface Account { // 查詢 public void queryAccount (); // 修改 public void updateAccount (); } <pre name="code" class="java"> /** * 介面實現類(包含業務邏輯) * 即:委託類 * @author Cassie */ public class AccountImpl implements Account{ @Override public void queryAccount() { System.out.println("查詢方法..."); } @Override public void updateAccount() { System.out.println("修改方法..."); } } </span>
第二:定義代理類,實現業務介面
<span style="font-family:KaiTi_GB2312;font-size:18px;">/**
* 代理類(增強AccountImpl的功能)
* @author Cassie
*/
public class AccountProxy implements Account{
private AccountImpl accountImpl;
/**
* 重寫預設建構函式
* @param accountImpl :真正要執行業務的物件
*/
public AccountProxy(AccountImpl accountImpl) {
this.accountImpl =accountImpl;
}
@Override
public void queryAccount() {
System.out.println("業務處理之前...");
// 呼叫委託類的方法,這是具體的業務方法
account>Impl.queryCount();
System.out.println("業務處理之後...");
}
@Override
public void updateAccount() {
System.out.println("業務處理之前...");
// 呼叫委託類的方法;
accountImpl.updateAccount();
System.out.println("業務處理之後...");
}
} </span>
第三:寫客戶端,我這裡寫的測試類。
<span style="font-family:KaiTi_GB2312;font-size:18px;">/**
* 測試Account類
* @author Cassie
*/
public class TestAccount {
public static void main(String[] args) {
AccountImpl accountImpl = new AccountImpl();
//在這裡傳入要呼叫的業務物件
AccountProxy accountProxy = new AccountProxy(accountImpl);
//開始呼叫業務物件的方法,這兩個方法都被增強了。
accountProxy.updateAcc>ount();
accountProxy.queryAccount();
}
} </span>
看到的執行效果:<span style="font-family:KaiTi_GB2312;font-size:18px;">業務處理之前...</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">修改方法...</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">業務處理之後...</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">業務處理之前...
查詢方法...</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">業務處理之後...</span>
好了,至此我們的靜態代理實現了,但是問題也跟著來了,觀察程式碼可以發現每一個代理類只能為一個介面服務,一個AccountProxy 類實現了一個Account介面,那麼我要是有多個介面,是不是要寫多個Proxy類與之對應。這樣一來程式開發中必然會產生過多的代理,而且,所有的代理操作除了呼叫的方法不一樣之外,其他的操作都一樣,則此時肯定是重複程式碼。解決這一問題最好的做法是可以通過一個代理類完成全部的代理功能,那就引入了我們的動態代理了。