初識代理模式

代理模式介紹

代理模式(Proxy Pattern)也稱為委托模式。

我們生活中處處都有代理模式的影子。對于程序員來說最常接觸的就是代理上網(wǎng)了,連上代理服務(wù)器,就可以看到墻外的世界;通過中介租房,也是一種代理。

代理模式定義: 為其他對象提供一種代理以控制對這個對象的訪問。

使用場景:當(dāng)無法或不想直接訪問某個對象時可以通過一個代理對象來間接訪問。(如果租房,你沒有精力去找到真正的房東,所以通過中介來租房)

代理模式的組成

  • 抽象角色: 通過接口或抽象類聲明真實(shí)角色實(shí)現(xiàn)的業(yè)務(wù)方法。
  • 真實(shí)角色: 實(shí)現(xiàn)抽象角色,定義真實(shí)角色所要實(shí)現(xiàn)的業(yè)務(wù)邏輯,供代理角色調(diào)用。
  • 代理角色:實(shí)現(xiàn)抽象角色,是真實(shí)角色的代理,通過真實(shí)角色的業(yè)務(wù)邏輯方法來實(shí)現(xiàn)抽象方法,并可以附加自己的操作。

優(yōu)點(diǎn):

  1. 職責(zé)清晰。真實(shí)的角色就是實(shí)現(xiàn)實(shí)際的業(yè)務(wù)邏輯,不用關(guān)心其他非本職責(zé)的事務(wù),通過后期的代理完成一件完成事務(wù),附帶的結(jié)果就是編程簡潔清晰。
  2. 代理對象可以在客戶端和目標(biāo)對象之間起到中介的作用,這樣起到了中介的作用和保護(hù)了目標(biāo)對象的作用。
  3. 高擴(kuò)展性

代理模式分類

代理模式分為靜態(tài)代理和動態(tài)代理。
靜態(tài)代理是由我們自己創(chuàng)造出代理類的源碼,就像通過中介來租房,我們需要先滿大街的跑找到這個中介。
動態(tài)代理則是由JDK提供的一個類來直接生成代理對象。就像同樣是租房,我們通過一個租房平臺,很容易就找到了中介。

靜態(tài)代理示例

這里我們還是以租房為示例,首先我們需要創(chuàng)建出一個接口,在接口中聲明業(yè)務(wù)方法(有房要出租)

public interface House {
    // 一個普通的租房業(yè)務(wù)
    public void rentingHouse();
}

然后我們再創(chuàng)建出真實(shí)角色(房東)和代理角色(中介)

// 房東
public class BeiJingOwner implements House{
    @Override
    public void rentingHouse() {
        System.out.println("我在北京有房要出租");
    }
}

// 中介
public class Proxy implements House{

    private House mHouse;

    public Proxy(House house) {
        this.mHouse = house;
    }

    @Override
    public void rentingHouse() {
        this.mHouse.rentingHouse();
    }

}

最后我們就可以去租房啦,當(dāng)然我們是通過中介來租房的

public class Myself {
    public static void main(String[] args) {
        BeiJingOwner owner = new BeiJingOwner();
        House house = new Proxy(owner);
        // 這樣,我們就通過中介租到了房
        house.rentingHouse();
    }
}

這樣就是一個代理模式的簡單使用,其主要還是一種委托機(jī)制,真實(shí)對象將方法的執(zhí)行委托給代理對象。
當(dāng)然代理類(中介)完全可以代理多個被代理類(房主),而具體到底是代理的哪個人,就要看代理類中所持有的實(shí)際對象類型,在此示例中是BeiJingOwner,所以就是賣的北京的房子,當(dāng)然也可以代理ShanghaiHouse了。

動態(tài)代理

靜態(tài)代理如上述示例那樣,代理者的代碼由我們自己編寫。
而動態(tài)代理則與靜態(tài)代理相反,jdk提供一個Proxy類可以直接給實(shí)現(xiàn)接口類的對象直接生成代理對象。
我們先了解一下動態(tài)代理相關(guān)的類和方法
Java.lang.reflect.Proxy類可以直接生成一個代理對象
方法名:
Proxy.newProxyInstance(): 產(chǎn)生代理類的實(shí)例。僅能代理實(shí)現(xiàn)至少一個接口的類
參數(shù)類型:
ClassLoader: 類加載器。固定寫法,和被代理類使用相同的類加載器即可。
Class[] interface: 代理類要實(shí)現(xiàn)的接口。固定寫法,和被代理類使用相同的接口即可。
InvocationHandler: 策略(方案)設(shè)計模式的應(yīng)用.

方法名:
InvocationHandler中的invoke方法:調(diào)用代理類的任何方法,此方法都會執(zhí)行
參數(shù)類型:
Object proxy: 代理對象本身的引用。一般用不著。
Method method: 當(dāng)前調(diào)用的方法。
Object[] args: 當(dāng)前方法用到的參數(shù)

相比于靜態(tài)代理,我們可以不用寫代理類,其他類都保留,然后調(diào)用方法如下

public class Myself {
    public static void main(String[] args) {
        House owner = new BeiJingOwner();
        House proxy = (House) Proxy.newProxyInstance(owner.getClass().getClassLoader(), owner.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke(owner, args);
            }
        });
        proxy.rentingHouse();
    }
}

因?yàn)檎{(diào)用代理類的任何方法,都會執(zhí)行InvocationHandler#invoke方法。所以我們還可以在真實(shí)類執(zhí)行之前或者之后,動一些手腳。
就像通過中介去租房,中介也是會從中收取一些好處費(fèi)的一樣。
現(xiàn)在,我們把rentingHouse改造成帶有參數(shù)的方法:

public interface House {
    // 我們加上了一個參數(shù),就如同房租
    public void rentingHouse(int price);
}
public class Myself {
    public static void main(String[] args) {
        House owner = new BeiJingOwner();
        House proxy = (House) Proxy.newProxyInstance(owner.getClass().getClassLoader(), owner.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 我們可以在這里進(jìn)行一些操作,就像中介收取好處費(fèi)一樣
                Object[] o = new Object[]{(Integer)args[0]/2};
                return method.invoke(owner, o);
            }
        });
        proxy.rentingHouse(100);
    }
}

在反射之前,我們對參數(shù)進(jìn)行一些改動,就可以做一些預(yù)處理之類的操作了。當(dāng)然也能進(jìn)行一些其他操作,比如數(shù)據(jù)庫的事務(wù)開啟/關(guān)閉。

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

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

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