相關文章
【設計模式】【一】設計六大原則
【設計模式】【二】單例模式的七種寫法
【設計模式】【三】建造者模式
【設計模式】【四】簡單工廠模式
【設計模式】【五】觀察者模式
【設計模式】【六】代理模式
【設計模式】【七】裝飾模式
【設計模式】【八】外觀模式
【設計模式】【九】模版方法模式
【設計模式】【十】工廠方法模式
【設計模式】【十一】策略模式
【設計模式】【十二】享元模式
【設計模式】【十三】抽象工廠模式
1.代理模式簡介
代理模式介紹
代理模式也叫委託模式,是結構型設計模式的一種。在現實生活中我們用到類似代理模式的場景有很多,比如代購、代理上網、打官司等。
定義
爲其他對象提供一種代理以控制這個對象的訪問。
代理模式結構圖
- Subject:抽象主題類,聲明真實主題與代理的共同接口方法。
- RealSubject:真實主題類,定義了代理所表示的真實對象,客戶端通過代理類間接的調用真實主題類的方法。
- ProxySubject:代理類,持有對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行。
- Client:客戶端類。
2.代理模式的簡單實現
假設我要買一個BV的包(博主我很喜歡一直買不起),國內的太貴了,我找了個代購來幫我海外購買,這樣能省好多錢,哈哈。
抽象主題類(Subject)
抽象主題類具有真實主題類和代理的共同接口方法,我想要代購,那共同的方法就是購買:
public interface IShop {
//購買
void buy();
}
真實主題類(RealSubject)
這個購買者LiuWangShu也就是我,實現了IShop接口提供的 buy()方法:
public class LiuWangShu implements IShop {
@Override
public void buy() {
System.out.println("購買");
}
}
代理類(ProxySubject)
我找的代理類同樣也要實現IShop接口,並且要持有被代理者,在buy()方法中調用了被代理者的buy()方法:
public class Purchasing implements IShop {
private IShop mShop;
public Purchasing(IShop shop){
mShop=shop;
}
@Override
public void buy() {
mShop.buy();
}
}
客戶端類(Client)
public class Client {
public static void main(String[] args){
//創建LiuWangShu
IShop liuwangshu=new LiuWangShu();
//創建代購者並將LiuWangShu作爲構造函數傳
IShop purchasing=new Purchasing(liuwangshu);
purchasing.buy();
}
}
看完客戶端類的代碼,其實也是很好理解,就是代理類包含了真實主題類(被代理者),最終調用的都是真實主題類(被代理者)實現的方法,在上面的例子就是LiuWangShu類的buy()方法,所以運行的結果就是“購買”。
3.動態代理的簡單實現
從編碼的角度來說,代理模式分爲靜態代理和動態代理,上面的例子是靜態代理,在代碼運行前就已經存在了代理類的class編譯文件,而動態代理則是在代碼運行時通過反射來動態的生成代理類的對象,並確定到底來代理誰。也就是我們在編碼階段不需要知道代理誰,代理誰我們將會在代碼運行時決定。Java提供了動態的代理接口InvocationHandler,實現該接口需要重寫invoke()方法。下面我們在上面靜態代理的例子上做修改:
創建動態代理類:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicPurchasing implements InvocationHandler{
private Object obj;
public DynamicPurchasing(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(obj, args);
return result;
}
}
在動態代理類中我們聲明一個Object的引用,該引用指向被代理類,我們調用被代理類的具體方法在invoke()方法中執行。接下來我們修改客戶端類代碼:
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args){
//創建LiuWangShu
IShop liuwangshu=new LiuWangShu();
//創建動態代理
DynamicPurchasing mDynamicPurchasing=new DynamicPurchasing(liuwangshu);
//創建LiuWangShu的ClassLoader
ClassLoader loader=liuwangshu.getClass().getClassLoader();
//動態創建代理類
IShop purchasing= (IShop) Proxy.newProxyInstance(loader,new Class[]{IShop.class},mDynamicPurchasing);
purchasing.buy();
}
}
4.代理模式的應用
代理模式類型
代理模式的類型主要有以下幾點:
- 遠程代理:爲一個對象在不同的地址空間提供局部代表,這樣系統可以將Server部分的事項隱藏。
- 虛擬代理:使用一個代理對象表示一個十分耗資源的對象並在真正需要時才創建。
- 安全代理:用來控制真實對象訪問時的權限。
- 智能指引:當調用真實的對象時,代理處理另外一些事,比如計算真實對象的引用計數,當該對象沒有引用時,可以自動釋放它;或者訪問一個實際對象時,檢查是否已經能夠鎖定它,以確保其他對象不能改變它。
代理模式使用場景
無法或者不想直接訪問某個對象時可以通過一個代理對象來間接的訪問。