代理模式:爲其他對象提供一種代理,以控制對這個對象的訪問,可以去掉某些功能,或者增加某些額外的服務.
例如汽車具有行駛的功能,如果想爲汽車再添加日誌,記錄行駛時間的工作時,便可以創建代理類進行其餘的操作.
1>創建一個interface包含汽車的move()方法
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
public interface Moveable {
void move();
}
2>真實的類(Car)和代理類(ProxyCar02)都需要實現這個接口
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
//使用集合的方式進行代理模式
public class ProxyCar02 implements Moveable {
private Car car01;
public ProxyCar02(Car car01) {
super();
this.car01 = car01;
}
@Override
public void move(){
long startTime = System.currentTimeMillis();
System.out.println("汽車開始行駛...");
car01.move();
long endTime = System.currentTimeMillis();
System.out.println("汽車停止行駛... "+(endTime-startTime));
}
}
3>測試類
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
public class ClientTest {
public static void main(String[] args) {
//使用集合方式
Car c = new Car();
Moveable m1 = new ProxyCar02(c);
m1.move();
}
}
從上面的例子可以看出代理模式的工作方式,首先,因爲ProxyCar02和Car都實現了共同的接口,這使我們可以在不改變原來接口的情況下,只要用Car對象的地方,都可以用ProxyCar02來代替.其在客戶和真實,ProxyCar02在Client和Car之間起了一箇中介作用,利用這個中介平臺,我們可以在把客戶請求傳遞給Car之前,做一些必要的預處理.
Java對代理模式的支持—–動態代理
上面的代理,我們強迫代理類ProxyCar02實現了抽象接口Moveable.這導致我們的代理類無法通用於其他接口,所以不得不爲每一個接口實現一個代理類.幸好,java爲代理模式提供了支持.
java主要是通過Proxy類和InvocationHandler接口來給實現對代理模式的支持的.
下面用java的代理機制來實現上面的例子
package com.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Created by panlu on 15-9-5.
*/
//事務處理器
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
//在該方法中添加具體的業務邏輯
/*
* proxy: 指代我們所代理的那個真實對象
* method: 指代的是我們所要調用真實對象的某個方法的Method對象
* args: 指代的是調用真實對象某個方法時接受的參數
* */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("汽車開始行駛...");
method.invoke(target);
long endTime = System.currentTimeMillis();
System.out.println("汽車停止行駛... "+(endTime-startTime));
return null;
}
}
通過上面的代碼可以看出,代理類TimeHandler 並沒有實現我們定義的Moveable接口,
而是實現了java的InvocationHandler接口,這樣就把代理汽車角色和我們的業務代碼分離開來,使代理對象能通用於其他接口.
其實InvocationHandler接口就是一種攔截機制,當系統中有了代理對象以後,對原對象(真實汽車)方法的調用,都會轉由InvocationHandler接口來處理,並把方法信息以參數的形式傳遞給invoke方法,這樣,我們就可以在invoke方法中攔截原對象的調用,並通過反射機制來動態調用原對象的方法.