有兩天沒寫博客了,主要是這兩天比較疲憊店煞;于是乎買了本書《牧羊少年奇幻之旅》一本《超越華爾街》一本蟹演;主要為了尋找迷失的方向和自己當初的理想;不忘初心顷蟀,方得始終酒请;今后更當修身養(yǎng)性,尋求內(nèi)心的富足鸣个;好了今天我們來看看使用率相當高的代理模式羞反;
看看定義:
Provide a surrogate or placeholder for another object to control access to it.(為其他對象提供
一種代理以控制對這個對象的訪問布朦。)
由定義可見;對其他對象提供一種代理昼窗,那就是有代理者和被代理者(委托類)是趴;就像總統(tǒng)發(fā)言人一樣,他所說idea都代表總統(tǒng)的意思膏秫;他是總統(tǒng)的代理者右遭;理清了原理我們就清晰多了后續(xù),做什么我們就不會有那么多為什么缤削。
首先我們看下靜態(tài)代理:
假設(shè)有這么一個場景:我們都知道京東商城搞得是自營窘哈,所以國內(nèi)服務和質(zhì)量和速度做的很好;如果所有貨源都從北京總部發(fā)貨那肯定是做不到次日達或者當日達的亭敢;那么就要在各地設(shè)立分部倉儲滚婉;這個是不是可以理解為代理模式;我尋找一個代理倉庫負責這一片地方的貨物供給:好了我們寫了Demo;
定義一個統(tǒng)一倉庫的接口
package com.ldl.proxytest;
public interface Warehouse {
public void receiveOrder();
public void findProduct();
public void packUpProduct();
public void sendOutProduct();
}
定義一個倉庫的實現(xiàn):
package com.ldl.proxytest;
public class WarehouseImpl implements Warehouse {
private String address;
public WarehouseImpl(String address) {
super();
this.address = address;
}
@Override
public void receiveOrder() {
System.out.println(address + "收到訂單了");
}
@Override
public void findProduct() {
System.out.println(address + "在尋找訂單");
}
@Override
public void packUpProduct() {
// TODO Auto-generated method stub
System.out.println(address + "在打包訂單了");
}
@Override
public void sendOutProduct() {
// TODO Auto-generated method stub
System.out.println(address + "發(fā)出訂單包裹了");
}
}
我們在搞一個代理類:
package com.ldl.proxytest;
public class WareHouseProxy implements Warehouse {
private Warehouse warehouse;
public WareHouseProxy(Warehouse warehouse) {
super();
this.warehouse = warehouse;
}
@Override
public void receiveOrder() {
// TODO Auto-generated method stub
this.warehouse.receiveOrder();
}
@Override
public void findProduct() {
// TODO Auto-generated method stub
this.warehouse.findProduct();
}
@Override
public void packUpProduct() {
// TODO Auto-generated method stub
this.warehouse.packUpProduct();
}
@Override
public void sendOutProduct() {
// TODO Auto-generated method stub
this.warehouse.sendOutProduct();
}
}
哈哈完事了我們搞個客戶端測試一下唄:
package com.ldl.proxytest;
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Warehouse wareHouse = new WarehouseImpl("深圳");
Warehouse wareHouseProxy = new WareHouseProxy(wareHouse);
wareHouseProxy.receiveOrder();
wareHouseProxy.findProduct();
wareHouseProxy.packUpProduct();
wareHouseProxy.sendOutProduct();
}
}
歐了看到了吧效果還可以帅刀;我們用WareHouseProxy類代理WarehouseImpl让腹;WarehouseImpl是個委托者;我委托你作為我的代理扣溺;是不是還挺簡單骇窍?這就是靜態(tài)代理模式;那么如果說京東像阿里一樣一分為4獨立運營該怎么辦锥余;難道我們要為4家分別實現(xiàn)一個接口分別搞一個代理嗎腹纳?那么代理會不會顯得冗余,代理除了調(diào)用方法不同其他是一樣的驱犹;作為開發(fā)者看到重復代碼就要想辦法抽瘸盎小;好了不賣關(guān)子了我們用動態(tài)代理解決這個問題:
動態(tài)代理即我們可以動態(tài)創(chuàng)建不同的代理類:
下面我們先改造一下Demo在解釋:
package com.ldl.proxytest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WareHouseIH implements InvocationHandler {
// 被代理者
private Class cls;
// 代理誰(被代理的勢力實例)
private Object obj;
public WareHouseIH(Object obj) {
super();
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
return result;
}}
測試一下:
package com.ldl.proxytest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Warehouse wareHouse = new WarehouseImpl("深圳");
InvocationHandler proxyHandler = new WareHouseIH(wareHouse);
// 我們動態(tài)創(chuàng)建一個代理對象
Warehouse proxy = (Warehouse) Proxy.newProxyInstance(wareHouse.getClass().getClassLoader(),
wareHouse.getClass().getInterfaces(), proxyHandler);
proxy.receiveOrder();
proxy.findProduct();
proxy.packUpProduct();
proxy.sendOutProduct();
// Warehouse wareHouseProxy = new WareHouseProxy(wareHouse);
// wareHouseProxy.receiveOrder();
// wareHouseProxy.findProduct();
// wareHouseProxy.packUpProduct();
// wareHouseProxy.sendOutProduct();
} }
InvocationHandler是JDK提供的動態(tài)代理接口雄驹,對被代理類的方法進行代理佃牛;其中invoke方法是接口InvocationHandler定義必須實現(xiàn)的,它完成對真實方法的調(diào)用医舆。我
們來詳細講解一下InvocationHandler接口俘侠,動態(tài)代理是根據(jù)被代理的接口生成所有的方法,
也就是說給定一個接口蔬将,動態(tài)代理會宣稱“我已經(jīng)實現(xiàn)該接口下的所有方法了”爷速,
所有被代理的方法都由InvocationHandler接管實際的處理任務
看一下通用類圖:
動態(tài)代理實現(xiàn)代理的職責,業(yè)務邏輯Subject實現(xiàn)相關(guān)的邏輯功能娃胆,兩者之間沒有必然的相互耦合的關(guān)系
注意 要實現(xiàn)動態(tài)代理的首要條件是:被代理類必須實現(xiàn)一個接口,回想一下前面的分
析吧等曼。當然了里烦,現(xiàn)在也有很多技術(shù)如CGLIB可以實現(xiàn)不需要接口也可以實現(xiàn)動態(tài)代理的方
式凿蒜。這個我們知道就好,今天的任務是把代理搞明白胁黑;其實你清楚了原理废封;只要記住Proxy類即可;用時拿來即用丧蘸;