天天看點

3.7 設計模式-代理模式1.簡介

1.簡介

在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。給目标對象提供一個代理對象,并由代理對象控制對目标對象的引用

2.靜态代理

2.1 概念

靜态代理在編譯時就已經實作,編譯完成後代理類是一個實際的class檔案。需要代理對象和目标對象實作一樣的接口。

  • 優點:可以在不修改目标對象的前提下擴充目标對象的功能。
  • 缺點:備援。由于代理對象要實作與目标對象一緻的接口,會産生過多的代理類。不易維護。一旦接口增加方法,目标對象與代理對象都要進行修改。

2.2案例

public interface ITask {
    void dispatchTask();
}

/**
 * 老闆
 */
public class Boss implements ITask {

    private static final String TAG = "Boss";


    @Override
    public void dispatchTask() {
        Log.d(TAG, "dispatchTask: ");
    }
}


/**
 * 秘書
 */
public class Secretary implements ITask {

    Boss  realObj;
    public Secretary( Boss  realObj) {
        this.realObj = realObj;
    }

    @Override
    public void dispatchTask() {

    }
}
 
           

調用

Boss boss = new  Boss();
        final Secretary proxyObj = new Secretary(boss);
        proxyObj.dispatchTask();
           

3.動态代理

動态代理對象不需要實作接口,但是要求目标對象必須實作接口,否則不能使用動态代理。

JDK提供了代理對象:

  • java.lang.reflect Proxy,主要方法為
static Object    newProxyInstance(
	ClassLoader loader,  //指定目前目标對象的類加載器
	Class<?>[] interfaces,    //目标對象實作的接口的類型
	InvocationHandler h      //事件處理器
) 
//傳回一個指定接口的代理類執行個體,該接口可以将方法調用指派到指定的調用處理程式。
           
  • java.lang.reflect InvocationHandler,主要方法為
Object  invoke(Object proxy, Method method, Object[] args) 
// 在代理執行個體上處理方法調用并傳回結果。
           

3.1 案例

public interface IUserDao {
      void save();
}

public class UserDao implements IUserDao{

    @Override
    public void save() {
        System.out.println("儲存資料");
    }
}

public class ProxyFactory {
    private Object target;// 維護一個目标對象

    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 為目标對象生成代理對象
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("開啟事務");

                        // 執行目标對象方法
                        Object returnValue = method.invoke(target, args);

                        System.out.println("送出事務");
                        return null;
                    }
                });
    }
}
           
IUserDao target = new UserDao();
 System.out.println(target.getClass());  //輸出目标對象資訊
 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
 System.out.println(proxy.getClass());  //輸出代理對象資訊
 proxy.save();  //執行代理方法