
一.定義
- 將一個復雜的構建與其表示相分離,使得同樣的構建過程可以創(chuàng)建不同的表示。
代理在結構上類似裝飾著,但目的不同,裝飾者模式為對象加上行為,而代理則是控制訪問 代理為另一個對象提供代表,以便客戶對對象的訪問
二.作用
- 職責清晰真實的角色就是實現實際的業(yè)務邏輯,不用關心其他非本職責的事務,通過后期的代理
完成一件事務,附帶的結果就是編程簡潔清晰。 - 高擴展性
三.案例
本章將講解普通代理和動態(tài)代理兩種代理方式
- 普通代理
大學畢業(yè)之后大學生們就開始前往不同的城市參加工作,有些公司提供住房還好,但是這種可能性基本不大,于是乎就得考慮住房問題,這個時候市場上就出現了房屋中介商,專門解決這樣類似的問題。下面是簡單的示意圖

IHouse接口有兩個方法房屋位置和房屋大小
public interface IHouse {
//位置
void location(String address);
//大小
void size(int size);
}
實現類House,這個類主要用來實現具體的業(yè)務邏輯,這里只打印這些信息,
public class House implements IHouse {
@Override
public void location(String address) {
System.out.println(address);
}
@Override
public void size(int size) {
System.out.println(size+"平方");
}
}
下面是代理模式的核心代理類,通過構造函數定義一個需要被代理的對象,同時它還可以具備自己的方法,作為一個房屋代理者,它還可以告訴你租房所需的費用
public class HomeProxy implements IHouse {
private IHouse house;
//構造函數定義一個租房
public HomeProxy() {
this.house = new House();
}
@Override
public void location(String address) {
this.house.location(address);
}
@Override
public void size(int size) {
this.house.size(size);
cost(size);
}
//合計
public void cost(int size) {
System.out.println(size * 5 + tip(size)+"$");
}
//中介費
public double tip(int size) {
return size * 5 * 0.35;
}
}
我們模擬一下租房的過程,如下所示:
public static void main(String[] args) {
//創(chuàng)建一個房屋中介商
IHouse proxy = new HomeProxy(house);
//租房的位置
proxy.location("上海");
//租房的大小
proxy.size(100);
}
運行結果如下:
上海
100平方
675.0$
這種模式下通過構造函數定義一個代理對象,進行代理。調用者只需要知道代理類是誰就可以了,結構更加清晰,屏蔽了
真實角色的變更對高層模塊的影響,真是角色只需要實現接口,實現具體的業(yè)務邏輯,想怎么改就怎么改,提高了擴展性
- 動態(tài)代理
動態(tài)代理需要實現InvocationHandler接口產生一個代理對象,InvocationHandler是JDK本身就提供好的的動態(tài)代理接口,這里用HomeIH去實現這個接口
public class HomeIH implements InvocationHandler {
//被代理的實例
Object obj;
//我要代理誰
public HomeIH(Object _obj) {
this.obj = _obj;
}
//調用被代理的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//方法執(zhí)行之前
System.out.println("before " + method.getName());
//執(zhí)行被代理的方法
Object result = method.invoke(this.obj, args);
return result;
}
}
這樣寫之后所有方法都由該Handler來進行處理,所有被代理的方法都由invoke方法去執(zhí)行,invoke的三個參數分別為proxy(代理對象 ),method(被調用方法),args(被調用方法的參數)還是延續(xù)上面的代碼,只需將main函數修改如下
public static void main(String[] args) {
//被代理實例
IHouse house = new House();
//通過構造函數傳入到Handler中
HomeIH handler = new HomeIH(house);
//動態(tài)產生一個代理者
IHouse proxy = (IHouse) Proxy.newProxyInstance(house.getClass().getClassLoader(),new Class[]{IHouse.class},handler);
//租房的位置
proxy.location("上海");
//租房的大小
proxy.size(100);
}
運行之后看結果:
before location
上海
before size
100平方
看到沒這就是動態(tài)代理,還是通過代理去租房,和普通代理的區(qū)別就是,動態(tài)代理不用創(chuàng)建代理類,不用實現方法接口,而且更加的靈活,更加的具備擴展性 ,當然,JDK的動態(tài)代理有一個需要注意的地方,這里的每個委托類都必須是要有接口的,如果你問我,沒有實現接口能不能被代理,我說能
四.總結
代理類不僅僅是一個隔離客戶端和委托類的中介。我們還可以借助代理來在增加一些功能,而不需要修改原有代碼,完美的體現了開閉原則。
真正的業(yè)務功能還是有被代理來實現,但是在實現業(yè)務類之前的一些公共服務,或者之后的服務。我們可以通過代理模式來實現