這篇文章討論Java中使用非常廣泛的代理模式,代理思想非常重要且比較難理解,大家有什么問(wèn)題或者建議歡迎一起討論
該系列其他文章:
- 安卓設(shè)計(jì)模式(一)面向?qū)ο罅笤O(shè)計(jì)原則
- 安卓設(shè)計(jì)模式(二)單例模式
- 安卓設(shè)計(jì)模式(三)Builder模式
- 安卓設(shè)計(jì)模式(四)裝飾者模式
- 安卓設(shè)計(jì)模式(五)代理模式
- 安卓設(shè)計(jì)模式(六)策略模式
- 安卓設(shè)計(jì)模式(七)模板方法模式
- 安卓設(shè)計(jì)模式(八)工廠方法模式
定義:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)
使用場(chǎng)景:當(dāng)無(wú)法或不想直接訪問(wèn)某個(gè)對(duì)象或訪問(wèn)某個(gè)對(duì)象存在困難時(shí)可以通過(guò)一個(gè)代理對(duì)象來(lái)間接訪問(wèn),為了保證保證客戶(hù)端使用的透明性,委托對(duì)象與代理對(duì)象需要實(shí)現(xiàn)相同的接口.
代理思想在現(xiàn)實(shí)生活中使用非常多,比如你出租或者出售自己的房子,會(huì)將房產(chǎn)信息放到房產(chǎn)中介,并告知價(jià)格范圍,由中介來(lái)尋找買(mǎi)家,買(mǎi)家直接與中介對(duì)接,中介帶看房,談價(jià)格,但是最后成交方案依然由你自己控制.
代理模式根據(jù)實(shí)現(xiàn)方式一般分為兩類(lèi):
- 靜態(tài)代理 StaticProxy
- 動(dòng)態(tài)代理 DynamicProxy
靜態(tài)代理
抽象主題:
/**
* 明星接口,抽象主題角色
*/
public interface IStar {
void show();//演出
}
具體主題1:
/**
* 歌手,具體主題角色
*/
public class Singer implements IStar {
@Override
public void show() {
Log.i("Singer", "演唱");
}
}
具體主題2:
/**
* 演員 具體主題角色
*/
public class Actor implements IStar {
@Override
public void show() {
Log.i("Actor","表演");
}
}
代理:
/**
* 經(jīng)紀(jì)人,代理角色
*/
public class Broker implements IStar {
private IStar mStar;
public Broker() {
mStar = new Actor();//默認(rèn)被代理者
}
public Broker(String demand) {
//代理內(nèi)部根據(jù)需求自動(dòng)分配實(shí)際操作人
if (demand.contains("唱歌")) {
mStar = new Singer();
} else {
mStar = new Actor();
}
}
@Override
public void show() {
Log.i("Broker", "經(jīng)紀(jì)人與活動(dòng)方先談好費(fèi)用與安保工作");
mStar.show();
}
}
使用:
/**
* 活動(dòng)舉辦方,客戶(hù)端角色
*/
public class StaticClient {
//舉辦活動(dòng)
public void event() {
Broker broker = new Broker();
broker.show();//主辦方直接與經(jīng)紀(jì)人確定演出事宜
//或者
Broker broker1 = new Broker("現(xiàn)場(chǎng)需要歌手唱歌");
broker1.show();//主辦方直接與經(jīng)紀(jì)人確定演出事宜
}
}
分析
- 靜態(tài)代理內(nèi)部持有主題的引用
- 一個(gè)代理可以代理多個(gè)主題,代理根據(jù)實(shí)際需求來(lái)控制具體的實(shí)現(xiàn)主題
- 代理可以在主題具體實(shí)現(xiàn)前后添加附加代碼,達(dá)到控制和擴(kuò)充的目的
動(dòng)態(tài)代理
由上面的代理實(shí)現(xiàn)可以看到,代理模式的核心就是代理者內(nèi)部持有被代理者的引用,從而達(dá)到控制的目的,為了簡(jiǎn)化與統(tǒng)一,JDK為我們提供了動(dòng)態(tài)代理(或者說(shuō)萬(wàn)能代理).
動(dòng)態(tài)代理:
/**
* 動(dòng)態(tài)代理
*/
public class AllProxy implements InvocationHandler {
private Object mObject;
public AllProxy(Object object) {
mObject = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Log.i("AllProxy", "凡是涉及到安全性操作,使用代理并日志記錄");
return method.invoke(mObject, objects);
}
}
使用:
/**
* 活動(dòng)方,動(dòng)態(tài)代理客戶(hù)端
*/
public class DynamicClient {
//舉辦活動(dòng)
public void event() {
IStar star = new Singer();
//star.show();//不使用代理
//動(dòng)態(tài)代理,原理:反射
AllProxy allBroker = new AllProxy(star);
ClassLoader classLoader = star.getClass().getClassLoader();
IStar iStar = (IStar) Proxy.newProxyInstance(classLoader, new Class[]{IStar.class}, allBroker);
iStar.show();
}
}
分析
- 動(dòng)態(tài)簡(jiǎn)化了代理的使用,一個(gè)代理即可代理所有主題
- 動(dòng)態(tài)代理使用到JDK自帶的
InvocationHandler
接口,通過(guò)反射來(lái)確定最終的實(shí)現(xiàn),并在代理中添加統(tǒng)一的控制代碼,非常適用于管理員日志記錄操作
關(guān)于代理模式與裝飾者模式
- 代理模式是一個(gè)應(yīng)用非常廣泛,實(shí)現(xiàn)方式不固定的設(shè)計(jì)模式,主要強(qiáng)調(diào)思想;裝飾者模式目的明確,實(shí)現(xiàn)方式固定
- 解決的問(wèn)題不同:代理模式用于對(duì)同一類(lèi)對(duì)象的控制,裝飾者模式則是繼承關(guān)系的替代方案,用于動(dòng)態(tài)增強(qiáng)功能
關(guān)于作者
- 簡(jiǎn) 書(shū):uncochen
- github:ChenZhen
- 新浪微博:@Chen丶振
- Email:18620156376@163.com