初識代理模式

代理模式介紹

代理模式(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)系作者
  • 序言:七十年代末逆趣,一起剝皮案震驚了整個濱河市蝶溶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖抖所,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梨州,死亡現(xiàn)場離奇詭異,居然都是意外死亡田轧,警方通過查閱死者的電腦和手機(jī)暴匠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來傻粘,“玉大人每窖,你說我怎么就攤上這事∧ㄍ龋” “怎么了岛请?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長警绩。 經(jīng)常有香客問我崇败,道長,這世上最難降的妖魔是什么肩祥? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任后室,我火速辦了婚禮,結(jié)果婚禮上混狠,老公的妹妹穿的比我還像新娘岸霹。我一直安慰自己,他們只是感情好将饺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布贡避。 她就那樣靜靜地躺著,像睡著了一般予弧。 火紅的嫁衣襯著肌膚如雪刮吧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天掖蛤,我揣著相機(jī)與錄音杀捻,去河邊找鬼。 笑死蚓庭,一個胖子當(dāng)著我的面吹牛致讥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播器赞,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垢袱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了港柜?” 一聲冷哼從身側(cè)響起惶桐,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后姚糊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡授舟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年救恨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片释树。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡肠槽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奢啥,到底是詐尸還是另有隱情秸仙,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布桩盲,位于F島的核電站寂纪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赌结。R本人自食惡果不足惜捞蛋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柬姚。 院中可真熱鬧拟杉,春花似錦、人聲如沸量承。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撕捍。三九已至拿穴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卦洽,已是汗流浹背贞言。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阀蒂,地道東北人该窗。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蚤霞,于是被迫代替她去往敵國和親酗失。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容