java 中的設(shè)計(jì)模式

代理模式是什么

代理模式是一種設(shè)計(jì)模式,簡(jiǎn)單說(shuō)即是在不改變?cè)创a的情況下鉴扫,實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的功能擴(kuò)展肝匆。

比如說(shuō)有一個(gè)買(mǎi)房的對(duì)象叫BuyHouser,這個(gè)對(duì)象有一個(gè)方法叫buyhouse();

    public void buyhouse() {
        System.out.println("我要買(mǎi)房");
    }

這是一個(gè)公共的買(mǎi)房對(duì)象荷憋,你不是很喜歡,所以你希望通過(guò)自己的方式買(mǎi)房褐望。也就是對(duì)目標(biāo)對(duì)象BuyHouser的buyhouser方法進(jìn)行功能擴(kuò)展勒庄。

    public void buyhouse() {
        System.out.println("買(mǎi)房先準(zhǔn)備錢(qián)");
        System.out.println("我買(mǎi)房了");
        System.out.println("買(mǎi)完后裝修");
    }

就這樣可以通過(guò)修改相關(guān)代碼實(shí)現(xiàn)上面的需求串前,但是一些情況下相關(guān)的代碼是無(wú)法修改的,這個(gè)時(shí)候我們的代理模式就閃亮登場(chǎng)了

Java中代理模式分為兩種

  1. 靜態(tài)代理
  2. 動(dòng)態(tài)代理

先說(shuō)一說(shuō)靜態(tài)代理

  1. 先準(zhǔn)備一個(gè)接口锅铅,靜態(tài)代理要求目標(biāo)對(duì)象和代理對(duì)象實(shí)現(xiàn)同一個(gè)接口
public interface BuyHouse {
    void buyhouse();
}

  1. 然后準(zhǔn)備目標(biāo)對(duì)象實(shí)現(xiàn)這個(gè)接口
public class YouBuyHouse implements BuyHouse {
    @Override
    public void buyhouse() {
        System.out.println("我要買(mǎi)房");
    }
}
  1. 然后創(chuàng)建我們的代理對(duì)象
public class ProxyBuyHouse implements BuyHouse {
    //創(chuàng)建一個(gè)對(duì)象用于接收目標(biāo)對(duì)象 
    private BuyHouse buyHouse;
    //這里通過(guò)構(gòu)造器在代理類(lèi)實(shí)例化的時(shí)候初始化目標(biāo)對(duì)象
    public ProxyBuyHouse(BuyHouse buyHouse){
        this.buyHouse=buyHouse;
    }
    //這里是代理對(duì)象的具體方法
    @Override
    public void buyhouse() {
        System.out.println("賣(mài)房先準(zhǔn)備錢(qián)");
        //這里調(diào)用了目標(biāo)對(duì)象的方法(這里是必須的酪呻,不然就算不上代理模式了)
        buyHouse.buyhouse();
        System.out.println("買(mǎi)完后裝修");
    }
}

代理已經(jīng)完成了,然后我們編寫(xiě)一個(gè)測(cè)試類(lèi)來(lái)看看效果

public class BuyHouseTest {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        BuyHouse youBuyHouse = new YouBuyHouse();
        //創(chuàng)建代理對(duì)象,并傳入目標(biāo)對(duì)象
        BuyHouse proxyBuyHouse = new ProxyBuyHouse(youBuyHouse);
        proxyBuyHouse.buyhouse();
    }
}

輸出結(jié)果是這樣的

賣(mài)房先準(zhǔn)備錢(qián)
我要買(mǎi)房
買(mǎi)完后裝修

總結(jié):其實(shí)這里做的事情無(wú)非就是盐须,創(chuàng)建一個(gè)代理類(lèi)ProxyBuyHouse玩荠,繼承了BuyHouse接口并實(shí)現(xiàn)了其中的方法。只不過(guò)這種實(shí)現(xiàn)特意包含了目標(biāo)對(duì)象的方法贼邓,正是這種特征使得看起來(lái)像是“擴(kuò)展”了目標(biāo)對(duì)象的方法阶冈。如果代理對(duì)象中只是簡(jiǎn)單地對(duì)buyhouse()方法做了另一種實(shí)現(xiàn)而沒(méi)有包含目標(biāo)對(duì)象的方法,也就不能算作代理模式了塑径。所以這里的包含是關(guān)鍵女坑。

缺點(diǎn):這種實(shí)現(xiàn)方式很直觀也很簡(jiǎn)單,但其缺點(diǎn)是代理對(duì)象必須提前寫(xiě)出统舀,如果接口層發(fā)生了變化匆骗,代理對(duì)象的代碼也要進(jìn)行維護(hù)。如果能在運(yùn)行時(shí)動(dòng)態(tài)地寫(xiě)出代理對(duì)象誉简,不但減少了一大批代理類(lèi)的代碼碉就,也少了不斷維護(hù)的煩惱,不過(guò)運(yùn)行時(shí)的效率必定受到影響闷串。這種方式就是接下來(lái)的動(dòng)態(tài)代理瓮钥。

2. 動(dòng)態(tài)代理(也叫JDK代理)

這里我們依據(jù)按照上面買(mǎi)房的例子進(jìn)行代理

public interface BuyHouse {
    void buyhouse();
}

public class YouBuyHouse implements BuyHouse {
    @Override
    public void buyhouse() {
        System.out.println("我要買(mǎi)房");
    }
}

動(dòng)態(tài)代理實(shí)現(xiàn)起來(lái)也很容易

public class BuyHoseTest2 {
    public static void main(String[] args) {
        //創(chuàng)建目標(biāo)對(duì)象
        YouBuyHouse youBuyHouse = new YouBuyHouse();
        //創(chuàng)建代理對(duì)象
        BuyHouse proxy = (BuyHouse) Proxy.newProxyInstance(
                youBuyHouse.getClass().getClassLoader(),
                youBuyHouse.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("買(mǎi)房先存錢(qián)");
                        Object returnValue = method.invoke(youBuyHouse,args);
                        System.out.println("買(mǎi)完房后裝修");
                        return returnValue;
                    }
                }
        );
        proxy.buyhouse();
    }
}

這里我們先創(chuàng)建了一個(gè)目標(biāo)對(duì)象,然后通過(guò) Proxy 類(lèi)的靜態(tài)方法newProxyInstance獲取代理類(lèi)對(duì)象

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

接收的三個(gè)參數(shù)依次為:

  • ClassLoader loader:指定當(dāng)前目標(biāo)對(duì)象使用類(lèi)加載器烹吵,寫(xiě)法固定
  • Class<?>[] interfaces:目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類(lèi)型碉熄,寫(xiě)法固定
  • InvocationHandler h:事件處理接口,需傳入一個(gè)實(shí)現(xiàn)類(lèi)(即代理類(lèi))肋拔,一般直接使用匿名內(nèi)部類(lèi)

總結(jié):這種方法因?yàn)榻?jīng)過(guò)jdk的封裝所以使用起來(lái)比較簡(jiǎn)單
缺點(diǎn):這種和靜態(tài)代理一樣需要實(shí)現(xiàn)接口才可以進(jìn)行相應(yīng)的操作锈津,如果不想這樣可以通過(guò)spring 的Cglib代理實(shí)現(xiàn)(這個(gè)下次寫(xiě))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凉蜂,隨后出現(xiàn)的幾起案子一姿,更是在濱河造成了極大的恐慌,老刑警劉巖跃惫,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異艾栋,居然都是意外死亡爆存,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)蝗砾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)先较,“玉大人携冤,你說(shuō)我怎么就攤上這事∠猩祝” “怎么了曾棕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)菜循。 經(jīng)常有香客問(wèn)我翘地,道長(zhǎng),這世上最難降的妖魔是什么癌幕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任衙耕,我火速辦了婚禮,結(jié)果婚禮上勺远,老公的妹妹穿的比我還像新娘橙喘。我一直安慰自己,他們只是感情好胶逢,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布厅瞎。 她就那樣靜靜地躺著,像睡著了一般初坠。 火紅的嫁衣襯著肌膚如雪和簸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天某筐,我揣著相機(jī)與錄音比搭,去河邊找鬼。 笑死南誊,一個(gè)胖子當(dāng)著我的面吹牛身诺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抄囚,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼霉赡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了幔托?” 一聲冷哼從身側(cè)響起穴亏,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎重挑,沒(méi)想到半個(gè)月后嗓化,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谬哀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年刺覆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片史煎。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谦屑,死狀恐怖驳糯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氢橙,我是刑警寧澤酝枢,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站悍手,受9級(jí)特大地震影響帘睦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谓苟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一官脓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涝焙,春花似錦卑笨、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至隧哮,卻和暖如春桶良,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沮翔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工陨帆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人采蚀。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓疲牵,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親榆鼠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子纲爸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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