天天看點

動态代理模式【大話設計模式】

代理模式

什麼是代理模式?

代理模式的定義:代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用。通俗的來講代理模式就是我們生活中常見的中介。

舉個例子來說明:假如說我現在想買一輛二手車,雖然我可以自己去找車源,做品質檢測等一系列的車輛過戶流程,但是這确實太浪費我得時間和精力了。我隻是想買一輛車而已為什麼我還要額外做這麼多事呢?于是我就通過中介公司來買車,他們來給我找車源,幫我辦理車輛過戶流程,我隻是負責選擇自己喜歡的車,然後付錢就可以了。用圖表示如下:

為什麼要用代理模式?

中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委托對象,而代理類對象可以在客戶類和委托對象之間起到中介的作用,其特征是代理類和委托類實作相同的接口。

開閉原則,增加功能:代理類除了是客戶類和委托類的中介之外,我們還可以通過給代理類增加額外的功能來擴充委托類的功能,這樣做我們隻需要修改代理類而不需要再修改委托類,符合代碼設計的開閉原則。代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事後對傳回結果的處理等。代理類本身并不真正實作服務,而是同過調用委托類的相關方法,來提供特定的服務。真正的業務功能還是由委托類來實作,但是可以在業務功能執行的前後加入一些公共的服務。例如我們想給項目加入緩存、日志這些功能,我們就可以使用代理類來完成,而沒必要打開已經封裝好的委托類。

代理概念:

1.真實對象:被代理的對象

2.代理對象:代理真實對象的對象

3.代理模式:代理對象代理真實對象,達到增強真實對象功能的的目的。

兩種代理:

1.靜态代理:有一個類檔案描述代理模式

2.動态代理:在記憶體中形成代理類。

實作步驟:

1.代理對象和真實對象實作相同的接口

2.代理對象=Proxy.newInstance();

3.使用代理對象

代碼案例(動态代理賣聯想電腦)

真實類

package 動态代理;
/*
 * 真實類
 */
public class Lenovo implements SaleCompeter{

	@Override
	public String sale(double money) {
		System.out.println("花了"+money+"買了一台電腦");
		return "聯想電腦";
	}

	@Override
	public void show() {
		
	}
}

           

接口

package 動态代理;

public interface SaleCompeter {
	public String sale(double money);
	
	public void show(); 
}

           

動态代理的步驟(固定寫法)

package 動态代理;

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

/**
 * 動态代理步驟
 */
public class ProxyTest {
    public static void main(String[] args) {
        //建立真實對象
        Lenovo lenovo=new Lenovo();

        //動态代理增強對象
        /*
           三個參數
              1.類加載器:真實對象.getClass().getClassLoader()
              2.接口數組:真實對象.getClass().getInterfaces()
              3.處理器:new InvocationHandler()

         */
        SaleCompeter proxy_lenovo = (SaleCompeter) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
            /*
               代理邏輯編寫的方法,代理對象調用的所有方法都會觸發該方法執行
                  參數:
                     1.proxy 代理對象
                     2.method 代理對象調用的方法,被封裝為對象。
                     3.args 代理對象調用方法時傳遞的實際參數
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //System.out.println("代理對象實作的方法");
                //判斷是否是sale方法
                if (method.getName().equals("sale")){
                    //1.增強參數
                    double money=(double)args[0];
                    money=money*0.85;
                    System.out.println("專車接");
                    //使用真實對象調用該方法
                    String  obj = (String) method.invoke(lenovo, money);
                    System.out.println("免費送貨");
                    //增強傳回值
                    return obj+"滑鼠墊";
                } else {
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }
            }
        });

        //調用方法
        String competer = proxy_lenovo.sale(8000);
        System.out.println(competer);
    }
}