Java設計模式之代理模式

  代理模式:爲其他對象提供一種代理,以控制對這個對象的訪問,可以去掉某些功能,或者增加某些額外的服務.
  例如汽車具有行駛的功能,如果想爲汽車再添加日誌,記錄行駛時間的工作時,便可以創建代理類進行其餘的操作.

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方法中攔截原對象的調用,並通過反射機制來動態調用原對象的方法.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章