代理模式
什麼是代理模式?
代理模式的定義:代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用。通俗的來講代理模式就是我們生活中常見的中介。
舉個例子來說明:假如說我現在想買一輛二手車,雖然我可以自己去找車源,做品質檢測等一系列的車輛過戶流程,但是這确實太浪費我得時間和精力了。我隻是想買一輛車而已為什麼我還要額外做這麼多事呢?于是我就通過中介公司來買車,他們來給我找車源,幫我辦理車輛過戶流程,我隻是負責選擇自己喜歡的車,然後付錢就可以了。用圖表示如下:
為什麼要用代理模式?
中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委托對象,而代理類對象可以在客戶類和委托對象之間起到中介的作用,其特征是代理類和委托類實作相同的接口。
開閉原則,增加功能:代理類除了是客戶類和委托類的中介之外,我們還可以通過給代理類增加額外的功能來擴充委托類的功能,這樣做我們隻需要修改代理類而不需要再修改委托類,符合代碼設計的開閉原則。代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事後對傳回結果的處理等。代理類本身并不真正實作服務,而是同過調用委托類的相關方法,來提供特定的服務。真正的業務功能還是由委托類來實作,但是可以在業務功能執行的前後加入一些公共的服務。例如我們想給項目加入緩存、日志這些功能,我們就可以使用代理類來完成,而沒必要打開已經封裝好的委托類。
代理概念:
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);
}
}