1. 程式人生 > 其它 >設計模式-23種設計模式-結構型-代理模式

設計模式-23種設計模式-結構型-代理模式

一、代理模式介紹


二、代理模式引入

1.靜態代理

程式碼實現(Java):

//介面
public interface ITeacherDao {

    void teach(); // 授課的方法
}
public class TeacherDao implements ITeacherDao {

    @Override
    public void teach() {
        System.out.println(" 老師授課中  。。。。。");
    }

}
//代理物件,靜態代理
public class TeacherDaoProxy implements
ITeacherDao{ private ITeacherDao target; // 目標物件,通過介面來聚合 //構造器 public TeacherDaoProxy(ITeacherDao target) { this.target = target; } @Override public void teach() { System.out.println("開始代理 完成某些操作。。。。。 ");//方法 target.teach(); System.out.println(
"提交。。。。。");//方法 } }
public class Client {

    public static void main(String[] args) {
        //建立目標物件(被代理物件)
        TeacherDao teacherDao = new TeacherDao();

        //建立代理物件, 同時將被代理物件傳遞給代理物件
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);

        //通過代理物件,呼叫到被代理物件的方法
        
//即:執行的是代理物件的方法,代理物件再去呼叫目標物件的方法 teacherDaoProxy.teach(); } }

2.動態代理(JDK代理、介面代理)

程式碼實現(Java):

//介面
public interface ITeacherDao {

    void teach(); // 授課方法
    void sayHello(String name);
}
public class TeacherDao implements ITeacherDao {

    @Override
    public void teach() {
        System.out.println(" 老師授課中.... ");
    }

    @Override
    public void sayHello(String name) {
        System.out.println("hello " + name);
    }

}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory {

    //維護一個目標物件 , Object
    private Object target;

    //構造器 , 對target 進行初始化
    public ProxyFactory(Object target) {

        this.target = target;
    }

    //給目標物件 生成一個代理物件
    public Object getProxyInstance() {

        //說明
        /*
         *  public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

            //1. ClassLoader loader : 指定當前目標物件使用的類載入器, 獲取載入器的方法固定
            //2. Class<?>[] interfaces: 目標物件實現的介面型別,使用泛型方法確認型別
            //3. InvocationHandler h : 事情處理,執行目標物件的方法時,會觸發事情處理器方法, 會把當前執行的目標物件方法作為引數傳入
         */
        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("JDK代理開始~~");
                        //反射機制呼叫目標物件的方法
                        Object returnVal = method.invoke(target, args);
                        System.out.println("JDK代理提交");
                        return returnVal;
                    }
                });
    }


}
public class Client {

    public static void main(String[] args) {
        //建立目標物件
        ITeacherDao target = new TeacherDao();

        //給目標物件,建立代理物件, 可以轉成 ITeacherDao
        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

        // proxyInstance=class com.sun.proxy.$Proxy0 記憶體中動態生成了代理物件
        System.out.println("proxyInstance=" + proxyInstance.getClass());

        //通過代理物件,呼叫目標物件的方法
        //proxyInstance.teach();

        proxyInstance.sayHello(" tom ");
    }

}

3.Cglib代理

程式碼實現(Java):

相關jar包:

public class TeacherDao {

    public String teach() {
        System.out.println(" 老師授課中  , 我是cglib代理,不需要實現介面 ");
        return "hello";
    }
}
import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyFactory implements MethodInterceptor {

    //維護一個目標物件
    private Object target;

    //構造器,傳入一個被代理的物件
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回一個代理物件:  是 target 物件的代理物件
    public Object getProxyInstance() {
        //1. 建立一個工具類
        Enhancer enhancer = new Enhancer();
        //2. 設定父類
        enhancer.setSuperclass(target.getClass());
        //3. 設定回撥函式
        enhancer.setCallback(this);
        //4. 建立子類物件,即代理物件
        return enhancer.create();

    }


    //重寫  intercept 方法,會呼叫目標物件的方法
    @Override
    public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
        System.out.println("Cglib代理模式 ~~ 開始");
        Object returnVal = method.invoke(target, args);
        System.out.println("Cglib代理模式 ~~ 提交");
        return returnVal;
    }

}
public class Client {

    public static void main(String[] args) {
        //建立目標物件
        TeacherDao target = new TeacherDao();
        //獲取到代理物件,並且將目標物件傳遞給代理物件
        TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();

        //執行代理物件的方法,觸發intecept 方法,從而實現 對目標物件的呼叫
        String res = proxyInstance.teach();
        System.out.println("res=" + res);
    }

}

4.代理模式的變體