概念
給某一個(gè)對(duì)象提供一個(gè)代理或占位符,并由代理對(duì)象來(lái)控制對(duì)原對(duì)象的訪問(wèn)。
代理模式里面有三種角色,需求者(客戶),代理,委托者(供應(yīng)商),有兩種代理模式,靜態(tài)代理和動(dòng)態(tài)代理,舉個(gè)例子說(shuō)明吧,電器店是代理,需要買電器的人就是需求者,電器的供應(yīng)商就是委托者,委托者因?yàn)榉N種原因不能自己親自買東西給客戶,因此需要一個(gè)代理幫忙賣,也就是電器店,然而電器店也有兩種,一種是專賣店,一種就是普通店,專賣店專門賣一個(gè)供應(yīng)商的東西,也就是只代理一個(gè)供應(yīng)商的產(chǎn)品。這種模式叫做靜態(tài)代理,不會(huì)變動(dòng)的代理,簡(jiǎn)單直接。然而大多數(shù)情況下,一個(gè)電器店都不會(huì)只賣一個(gè)供應(yīng)商的產(chǎn)品,而是會(huì)同時(shí)賣多個(gè)供應(yīng)商的產(chǎn)品,客戶想要啥,就賣啥,通吃類型,這種模式就叫動(dòng)態(tài)代理。下面重點(diǎn)講一講java中這兩種模式的使用。
靜態(tài)代理
一個(gè)代理就對(duì)應(yīng)一個(gè)委托者,在Java中,等于一個(gè)java代理類對(duì)應(yīng)一個(gè)委托者類。具體的代碼如下:
委托者和代理需要實(shí)現(xiàn)的公共接口
public interface Subject {
void requst();
}
委托者
public class RealSubject implements Subject {
@Override
public void requst() {
Log.i("huan","realSubject");
}
}
代理
public class SubjectProxy implements Subject {
private RealSubject subject;
public SubjectProxy(RealSubject subject) {
this.subject = subject;
}
@Override
public void requst() {
Log.i("huan","SubjectProxy");
this.subject.requst();
}
}
客戶調(diào)用
RealSubject subject = new RealSubject();
SubjectProxy proxy = new SubjectProxy(subject);
proxy.requst();
優(yōu)點(diǎn):簡(jiǎn)單易懂
缺點(diǎn):一個(gè)代理只能代理一個(gè)委托者,對(duì)應(yīng)到j(luò)ava項(xiàng)目中,如果有很多委托者就會(huì)急劇的增加很多的代理類,導(dǎo)致類的急劇膨脹。其次,如果委托者事先不明確,就無(wú)法使用。
這個(gè)時(shí)候就出現(xiàn)了動(dòng)態(tài)代理,代理類可以事先不知道委托者是啥,而且代理類是通用的,可以代理任何委托者。
動(dòng)態(tài)代理
Java JDK提供了實(shí)現(xiàn)方式,具體如下
委托者接口
public interface ICar {
void drive();
void stop();
}
真實(shí)委托者
public class MyCar implements ICar {
@Override
public void drive() {
Log.i("huan","drive");
}
@Override
public void stop() {
Log.i("huan","stop");
}
}
public class CarInvocation implements InvocationHandler {
private Object mObject ;
public CarInvocation(Object mObject) {
this.mObject = mObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.i("huan", "invoke: method: "+method.getName());
return method.invoke(mObject,args);
}
}
MyCar myCar = new MyCar();
ICar carProxy = (ICar) Proxy.newProxyInstance(myCar.getClass().getClassLoader(),
myCar.getClass().getInterfaces(),new CarInvocation(myCar));
carProxy.drive();
carProxy.stop();
動(dòng)態(tài)代理利用類加載在運(yùn)行時(shí)動(dòng)態(tài)生成接口的代理類,并且利用反射原理,處理接口的方法,好處是不需要寫很多類,代碼簡(jiǎn)單。壞處是利用反射加大了內(nèi)存的負(fù)擔(dān)。
代理除了可以在調(diào)用委托類之前或者之后做一些額外的處理外,還有一個(gè)好處,可以偽裝委托類,就想賣東西的商家一樣,為了節(jié)約成本可以使用假貨來(lái)欺騙消費(fèi)者一樣,消費(fèi)者是無(wú)法識(shí)別的,消費(fèi)者只想要得到結(jié)果,在實(shí)際的代碼中也是可以這么寫的,例如:
public class CarInvocation implements InvocationHandler {
public CarInvocation() {
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.i("huan", "invoke: method: "+method.getName());
return "我是假貨,哈哈哈";
}
}
這種方式能夠方便代理類靈活的處理每一個(gè)方法。在Retrofit中有明顯的應(yīng)用。