Java設計模式--靜態代理與動態代理

Java靜態代理與動態代理

1.靜態代理(通過接口實現類去代理另一個接口實現類)

  • 解釋:靜態代理就比如租房這個事件,房東是真實對象,中介是代理對象,我是客戶,我要去找中介才能租房子(比自己找更方便,還有中介服務)。房東實現租房接口能出租房子,中介實現租房接口也能出租房子,但是房子是房東的,中介只能代理,於是中介只能靠房東(真實對象)實現出租房子,當然中介還可以加上其它自己想要的操作
  • 例子:

租房接口:

package com.lxf.demo01;

//租房接口
public interface Rent {
    public void rent();
}

房東(真實對象):

package com.lxf.demo01;


//房東對象
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房東要出租房子");
    }
}

中介(代理對象)

package com.lxf.demo01;

public class Proxy implements Rent{
    private Host host;

    public Proxy() {
    }
    //將真實對象賦給host
    public setHost(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        //看房子
        seeHouse();
        //籤合同
        singContract();
        //出租房子
        host.rent();
        //收費
        fare();
    }
    //看房
    public void seeHouse(){
        System.out.println("中介帶你看房");
    }
    //收中介費
    public void fare(){
        System.out.println("中介收中介費");
    }
    //籤合同
    public void singContract(){
        System.out.println("籤租賃合同");
    }
}

客戶(測試實例):

package com.lxf.demo01;

public class Client {
    public static void main(String[] args) {
        //房東:真實對象
        Host host=new Host();
        //代理:代理對象
        Proxy proxy = new Proxy();
		//將真實對象傳給代理對象
        proxy.setHost(Host host);
        //找中介租房(中介在中間撈油水)
        proxy.rent();
    }
}

2.動態代理

  • 解釋:再次看租房這個事件,房東是真實對象,中介是代理對象,我是客戶,我要去找中介才能租房子。房東實現租房接口能出租房子,此時中介不實現租房接口,建一個生成代理類的類(通過set或者構造函數接收真實對象,生成代理類),生成代理類的類實現InvocationHandler接口,然後將房東丟入生成代理類的類生成中介代理類,這個於是中介代理類就可以出租房子了,當然中介還可以加上其它自己想要的操作
  • 例子:

租房接口:

package com.lxf.demo01;

//租房接口
public interface Rent {
    public void rent();
}

房東接口:

package com.lxf.demo01;

//房東對象
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房東要出租房子");
    }
}

生成代理類的類:

package com.lxf.demo03;

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

//實現代理類生成的類
public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的真實對象
    private Rent rent;

    //設置真實對象
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理類
    public Object getProxy(){
//Proxy.newProxyInstance(ClassLoader loader,Class<?>[] Ingterfaces,InvocationHandler h);
       //第一個參數:真實對象的類加載器
        //第二個參數:真實對象實現的所有的接口
        //第三個參數: 接口,傳遞一個匿名內部類對象
        return Proxy.newProxyInstance(rent.getClass().getClassLoader(),
                                  rent.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //動態代理的本質:使用反射機制實現!
        //實現方法
        Object result = method.invoke(rent, args);

        return result;
    }


}

客戶(測試實例):

package com.lxf.demo03;

public class Client {
    public static void main(String[] args) {
        //真實角色
        Host host = new Host();

        //獲取代理角色的類
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        //將真實角色加入
        handler.setRent(host);
        //代理角色
        Rent proxy = (Rent) handler.getProxy();

		//實現方法
        proxy.rent();
    }
}

3.靜態代理與動態代理異同

  • 相同處:都是通過代理對象去實現方法,並且都可以加上其它操作。

  • 不同處:靜態代理是通過代理對象實現類去代理真實對象實現類,而動態代理是通過一個生成代理類的類去生成代理對象,動態代理的好處在於"很靈活"。靜態代理的代理對象是一個實際的類,要是真實對象發生改變,代理對象也要改。而動態代理的代理對象通過類產生,而不完全依賴於類,當真實對象發生改變也沒事,甚至可以將生成代理類的類改成萬能類:

    package com.lxf.demo04;
    
    import com.lxf.demo03.Rent;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    //實現代理類生成的類
    public class ProxyInvocationHandler implements InvocationHandler {
        //被代理的接口
        private Object target;
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        //生成代理類
        public Object getProxy(){
           return Proxy.newProxyInstance(target.getClass().getClassLoader(),
           target.getClass().getInterfaces(),this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable   	{
            System.out.println(method.getName());
            //動態代理的本質:使用反射機制實現!
            Object result = method.invoke(target, args);
    
            return result;
        }
    
    }
    

    動態代理分類補充:

    1. 基於接口:jdk動態代理類
    2. 基於類:cglib動態代理類
    3. java字節碼實現:javassist(用在JBoss服務器上)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章