適配器模式缀匕,裝飾模式纳决,代理模式異同

菜鳥(niǎo)版JAVA設(shè)計(jì)模式—適配器模式,裝飾模式乡小,代理模式異同

一阔加、概念

適配器模式,允許因?yàn)榻涌诓患嫒荻荒茉谝黄鸸ぷ鞯念惞ぷ髟谝黄鹇樱龇ㄊ菍㈩愖约旱慕涌诎谝粋€(gè)已存在的類中胜榔。
裝飾器模式,原有的不能滿足現(xiàn)有的需求零远,對(duì)原有的進(jìn)行增強(qiáng)苗分。
代理模式,同一個(gè)類而去調(diào)用另一個(gè)類的方法牵辣,不對(duì)這個(gè)方法進(jìn)行直接操作摔癣。

適配器的特點(diǎn)在于兼容,從代碼上的特點(diǎn)來(lái)說(shuō),適配類與原有的類具有相同的接口择浊,并且持有新的目標(biāo)對(duì)象戴卜。就如同一個(gè)三孔轉(zhuǎn)2孔的適配器一樣,他有三孔的插頭琢岩,可以插到三孔插座里投剥,又有兩孔的插座可以被2孔插頭插入。適配器模式是在于對(duì)原有3孔的改造担孔。在使用適配器模式的時(shí)候江锨,我們必須同時(shí)持有原對(duì)象,適配對(duì)象糕篇,目標(biāo)對(duì)象啄育。。拌消。挑豌。

裝飾器模式特點(diǎn)在于增強(qiáng),他的特點(diǎn)是被裝飾類和所有的裝飾類必須實(shí)現(xiàn)同一個(gè)接口墩崩,而且必須持有被裝飾的對(duì)象氓英,可以無(wú)限裝飾。

代理模式的特點(diǎn)在于隔離鹦筹,隔離調(diào)用類和被調(diào)用類的關(guān)系铝阐,通過(guò)一個(gè)代理類去調(diào)用。

總的來(lái)說(shuō)就是如下三句話:

  • 適配器模式是將一個(gè)類(a)通過(guò)某種方式轉(zhuǎn)換成另一個(gè)類(b).
  • 裝飾模式是在一個(gè)原有類(a)的基礎(chǔ)之上增加了某些新的功能變成另一個(gè)類(b).
  • 代理模式是將一個(gè)類(a)轉(zhuǎn)換成具體的操作類(b).
二盛龄、例子

先簡(jiǎn)單介紹一下饰迹,公司有一個(gè)ORDER系統(tǒng),專門用于提供訂單管理的接口余舶,提供給O2O商城啊鸭,WAP商城,手機(jī)類APP匿值,微信等客戶端調(diào)用赠制。ORDER系統(tǒng)在上線之時(shí),已經(jīng)包含了非常完整的數(shù)據(jù)操作挟憔。

現(xiàn)手機(jī)類APP需要升級(jí)钟些,老的接口可能不能滿足需求,如原O2O訂單提貨延長(zhǎng)有效期接口需要提供截至?xí)r間和訂單號(hào)绊谭,新APP可能不提供截至?xí)r間政恍,只需要提供訂單號(hào)即可延長(zhǎng)時(shí)間。而老的接口又不能修改达传,因?yàn)槔系膐rder接口是針對(duì)所有平臺(tái)的篙耗,那么必須將新接口要求與原接口進(jìn)行適配迫筑。。宗弯。

解決方案如下:新增AppAdepter類脯燃,用來(lái)適配老的接口,同時(shí)開(kāi)發(fā)給新的接口蒙保。辕棚。。邓厕。

先給出原接口和實(shí)現(xiàn)類

/**
 * 原接口逝嚎,需要傳入orderId,時(shí)間
 *
 */
public interface SourceOrderApi {
    public void updateDate(String orderId,String date,String client);
}

public class SourceOrderApiImpl implements SourceOrderApi{
    @Override
    public void updateDate(String orderId, String date, String client) {
        System.out.println(client+"已將訂單"+orderId+"的有效期延長(zhǎng)至"+date);       
    }
}

public class Test {
    public static void main(String[] args) {
        SourceOrderApi sourceOrderApi = new SourceOrderApiImpl();
        sourceOrderApi.updateDate("123456", "2014-10-15", "user");
    }
}
//運(yùn)行結(jié)果:user已將訂單123456的有效期延長(zhǎng)至2014-10-15

新的接口和實(shí)現(xiàn)類:

public interface AppOrderApi {
    //只需要傳入訂單Id即可
    public void updateDate(String orderId,String client);
}

public class AppOrderApiImpl implements AppOrderApi{
    SourceOrderApi sourceOrderApi;
    public AppOrderApiImpl(){
        sourceOrderApi = new SourceOrderApiImpl();
    }

    @Override
    public void updateDate(String orderId,String client) {
        //這里適配的方式隨意邑狸,但是保證是要完全兼容原有的懈糯,就是保證調(diào)用原有的接口
        sourceOrderApi.updateDate(orderId, "9999-12-31",client);
    }
}

public class Test {
    public static void main(String[] args) {
        AppOrderApi appOrderApi = new AppOrderApiImpl();
        appOrderApi.updateDate("123456", "user");
    }
}
//運(yùn)行結(jié)果:user已將訂單123456的有效期延長(zhǎng)至9999-12-31

在這套代碼中,新的實(shí)現(xiàn)類持有了老接口的對(duì)象单雾,就是把這個(gè)對(duì)象new 出來(lái)。她紫。硅堆。然后在新的方法里,進(jìn)行適配操作贿讹。而這里所謂的適配就是兼容老接口和兼容新接口渐逃。兼容老接口非常簡(jiǎn)單,就是直接調(diào)用老的方法即可民褂。而兼容新接口就是你所要去做的業(yè)務(wù)邏輯茄菊。。赊堪。比如我這里做了比較簡(jiǎn)單的操作面殖,app類的統(tǒng)一傳入“9999-12-31”,這些都是根據(jù)具體的項(xiàng)目需求去實(shí)現(xiàn)你的業(yè)務(wù)代碼哭廉〖沽牛看到這,很多人會(huì)覺(jué)得 這樣的代碼是不是很常見(jiàn)遵绰。辽幌。。椿访。我自己都特意去翻了一下我之前的代碼乌企,很多類似的寫(xiě)法。成玫。加酵。其實(shí)設(shè)計(jì)模式很多時(shí)候都融入到我們的代碼中端辱,只是我們沒(méi)有去理解這種模式,所以就算你自己寫(xiě)出來(lái)了虽画,都不知道這是一種適配器模式舞蔽。。码撰。

那么再回頭來(lái)說(shuō)代理模式渗柿,在代碼上,和適配器模式有著相似的地方脖岛!

再比如朵栖,現(xiàn)在我們公司的系統(tǒng)又要進(jìn)行升級(jí),我們?cè)鹊慕涌跊](méi)有加入安全機(jī)制柴梆,導(dǎo)致了任何人都可以隨意調(diào)用這個(gè)接口陨溅,現(xiàn)在公司需要對(duì)這個(gè)接口進(jìn)行改造,只其只能被admin這個(gè)客戶端調(diào)用绍在,其他用戶一律要輸入賬號(hào)密碼才能調(diào)用门扇。那么上面原接口和類不需要改動(dòng),我們只需要新增代理器即可偿渡。臼寄。。

這里就會(huì)顯出代理模式和適配器模式最大的區(qū)別溜宽,代理模式是與原對(duì)象實(shí)現(xiàn)同一個(gè)接口吉拳,而適配器類則是匹配新接口,說(shuō)白了适揉,實(shí)現(xiàn)一個(gè)新的接口留攒。


public class ProxySourceOrderApiImpl implements SourceOrderApi {
    SourceOrderApi sourceOrderApiImpl;
    public ProxySourceOrderApiImpl(){
        sourceOrderApiImpl = new SourceOrderApiImpl();
    }

    @Override
    public void updateDate(String orderId, String date, String client) {
        //進(jìn)行判斷,如果是admin則更新否則讓其輸入賬號(hào)密碼
        if("admin".equals(client)){
            sourceOrderApiImpl.updateDate(orderId, date, client);
        }else{
            System.out.println("賬號(hào)不是admin嫉嘀,沒(méi)有查詢權(quán)限炼邀,請(qǐng)輸入以admin操作");
        }
    }
}

這里的代理類必須要持要實(shí)現(xiàn)原接口和持有原接口的對(duì)象,才能稱之為代理類吃沪。

這樣汤善,我們不需要修改原先的實(shí)現(xiàn)類,用一個(gè)代理類來(lái)進(jìn)行過(guò)濾票彪。有些人可能有這樣的疑惑红淡,為什么不直接在原實(shí)現(xiàn)類中修改,記住JAVA設(shè)計(jì)模式的基本原則降铸,對(duì)內(nèi)關(guān)閉修改在旱。

假如你并沒(méi)有對(duì)方的類,別人只是提供給你這樣一個(gè)可以操作的JAR包你如何去做推掸?把JAR包反編譯桶蝎,再修改驻仅?又假如某些地方可以直接調(diào)用原有接口,你如果修改原有的實(shí)現(xiàn)類登渣,豈不是對(duì)其他的地方也造成了影響噪服?不能修改原有代碼這是基本原則。

最后胜茧,就是裝飾器模式粘优,裝飾器模式與相對(duì)于上面2種模式更好理解,差別也最大呻顽。

假如說(shuō)雹顺,現(xiàn)在這個(gè)延長(zhǎng)訂單,不光可以延長(zhǎng)訂單提貨有效期廊遍,可以延長(zhǎng)訂單的退貨有效期嬉愧。

這就是一個(gè)典型的裝飾器,你需要做的是豐富原接口的功能喉前,并且不改動(dòng)原先的接口没酣。


public class NewSourceOrderApiImpl implements SourceOrderApi {

    SourceOrderApi sourceOrderApi;
    public NewSourceOrderApiImpl(SourceOrderApi sourceOrderApi){
        this.sourceOrderApi = sourceOrderApi;
    }
    @Override
    public void updateDate(String orderId, String date, String client) {
        sourceOrderApi.updateDate(orderId, date, client);
        System.out.println(client+"已將訂單"+orderId+"的退款期延長(zhǎng)至"+date);       
        
    }

}

在裝飾器模式中,必須要有被裝飾的類和裝飾的類被饿。四康。在這套代碼中,原先SourceOrderApi的對(duì)象就是被裝飾的類狭握,而新建NewSourceOrderApiImpl 就是裝飾類,裝飾類必須把被裝飾的對(duì)象當(dāng)作參數(shù)傳入疯溺。

這就是和代理模式的代碼不同之處论颅,代理模式一定是自身持有這個(gè)對(duì)象,不需要從外部傳入囱嫩。而裝飾模式的一定是從外部傳入恃疯,并且可以沒(méi)有順序,按照代碼的實(shí)際需求隨意挑換順序墨闲,就如你吃火鍋先放白菜還是先放丸子都可以今妄。

再?gòu)氖褂蒙蟻?lái)看,代理模式注重的是隔離限制鸳碧,讓外部不能訪問(wèn)你實(shí)際的調(diào)用對(duì)象盾鳞,比如權(quán)限控制,裝飾模式注重的是功能的拓展瞻离,在同一個(gè)方法下實(shí)現(xiàn)更多的功能腾仅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市套利,隨后出現(xiàn)的幾起案子推励,更是在濱河造成了極大的恐慌鹤耍,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件验辞,死亡現(xiàn)場(chǎng)離奇詭異稿黄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)跌造,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門杆怕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鼻听,你說(shuō)我怎么就攤上這事财著。” “怎么了撑碴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵撑教,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我醉拓,道長(zhǎng)伟姐,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任亿卤,我火速辦了婚禮愤兵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘排吴。我一直安慰自己秆乳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布钻哩。 她就那樣靜靜地躺著屹堰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪街氢。 梳的紋絲不亂的頭發(fā)上扯键,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音珊肃,去河邊找鬼荣刑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛伦乔,可吹牛的內(nèi)容都是我干的厉亏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼评矩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼叶堆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起斥杜,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤虱颗,失蹤者是張志新(化名)和其女友劉穎沥匈,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體忘渔,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡高帖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畦粮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猪勇。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寞宫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雪隧,我是刑警寧澤漓糙,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布卿闹,位于F島的核電站捺宗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏钩蚊。R本人自食惡果不足惜贡翘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砰逻。 院中可真熱鬧鸣驱,春花似錦、人聲如沸蝠咆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刚操。三九已至递胧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赡茸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工祝闻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留占卧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓联喘,卻偏偏與公主長(zhǎng)得像华蜒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子豁遭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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