代理模式

概念

給某一個(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)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容