摘要:轉(zhuǎn)載請(qǐng)注明出處作者地址本文出自簡(jiǎn)書人人都會(huì)設(shè)計(jì)模式教程簡(jiǎn)介閱讀對(duì)象本篇教程適合新手閱讀,老手直接略過(guò)教程難度初級(jí),本人水平有限,文章內(nèi)容難免會(huì)出現(xiàn)問(wèn)題,如果有問(wèn)題歡迎指出,謝謝正文一什么是適配器模式生活中的適配器比如電腦轉(zhuǎn)接器這里主要是指連
PS:轉(zhuǎn)載請(qǐng)注明出處
作者: TigerChain
地址: http://www.jianshu.com/p/1edf5d944abb
本文出自 TigerChain 簡(jiǎn)書 人人都會(huì)設(shè)計(jì)模式教程簡(jiǎn)介
1、閱讀對(duì)象
本篇教程適合新手閱讀,老手直接略過(guò)
2、教程難度
初級(jí),本人水平有限,文章內(nèi)容難免會(huì)出現(xiàn)問(wèn)題,如果有問(wèn)題歡迎指出,謝謝
一、什么是適配器模式 1、生活中的適配器正文
比如電腦轉(zhuǎn)接器「這里主要是指連接電腦和投影儀的」,以我的 MAC 電腦為例子,我們公司的投影支持 VGA 和 HDMI ,但是我的 MAC 電腦只有一個(gè) MINI DP 接口,如何把 MINI DP 轉(zhuǎn)成 VGA 或 HDMI ,那么我就買了這個(gè)玩意「全稱 MINI DP 轉(zhuǎn) VGA & HDMI 適配器」,這東西就是一個(gè)適配器
這個(gè)適配器就可以把 MAC 和有 VGA 或 HDMI 的設(shè)備連接起來(lái)了,如下:
類似的還有電腦電源適配器,變壓器「也是一種適配器」,其實(shí)凈水器也可以看作是一種適配器「把雜水變成純凈水」,等等
2、程序中的適配器比如我們對(duì)接第三方的接口到我們的系統(tǒng)「對(duì)方給我們的接口,我們現(xiàn)在的接口對(duì)接不起來(lái)」
我們就需要寫一個(gè)中間層「適配器」,做為一個(gè)橋梁,把兩個(gè)接口連接起來(lái)
適配器模式的定義
通俗的說(shuō)適配器模式就是把兩個(gè)不兼容的接口連接起來(lái),類似一個(gè)橋梁的作用
注:適配器模式類比一個(gè)橋梁作用「它的作用不僅僅連接這么簡(jiǎn)單,還有轉(zhuǎn)化等操作,橋梁就是為了方便理解」
適配器模式的結(jié)構(gòu)
角色 | 類別 | 說(shuō)明 |
---|---|---|
Target | 目標(biāo)角色 | 是一個(gè)接口,也就是我們期待要轉(zhuǎn)化成的接口 |
Adaptee | 源角色 | 原始的類或接口對(duì)象 |
Adapter | 適配器角色 | 把源角色轉(zhuǎn)化成目標(biāo)角色的類 |
適配器模式的分類
1、類適配器模式
類適配器簡(jiǎn)單的 UML
總結(jié)一下就是:適配器「Adapter」繼承源類「Src」并且實(shí)現(xiàn)目標(biāo)「Dst」接口,來(lái)實(shí)現(xiàn) Src-->Dst 的轉(zhuǎn)換
2、對(duì)象適配器模式
對(duì)象適配器簡(jiǎn)單的 UML
總結(jié)一下就是:適配器「Adapter」持有源類「Src」的引用,并實(shí)現(xiàn)目標(biāo)「Dst」接口,來(lái)實(shí)現(xiàn) Src--> Dst 的轉(zhuǎn)化
3、接口適配器模式
對(duì)于這種模式「資料上也沒(méi)有說(shuō)有這種模式,我是在寫代碼的過(guò)程中發(fā)現(xiàn)可以這樣寫」,我持保留意見,如果有什么問(wèn)題,大家完全可以說(shuō)適配器模式的分類就有以上兩種模式,可我認(rèn)為這是適配器模式的一個(gè)變種
接口適配器簡(jiǎn)單的 UML
*總結(jié)一下就是: 適配器實(shí)現(xiàn)源和目標(biāo),把源轉(zhuǎn)化成目標(biāo)這么一個(gè)過(guò)程
二、適配器模式舉例1、Mac 電腦連接投影儀適配器
以開頭的例子為例子, MAC 電腦要連接投影儀器,需要一個(gè) MINI DP 轉(zhuǎn) VGA & HDMI 適配器,然后才能連接上投影儀
所以這里目標(biāo)是 VGAORHDMI ,源是 MINI DP 適配器就是上面的那根線
類適配投影儀和 MAC 電腦簡(jiǎn)單的 UML
根據(jù) UML 擼碼
使用類適配器模式
1、定義目標(biāo)接口 VgaOrHdmi
/** * 目標(biāo)角色,對(duì)投影儀來(lái)說(shuō)就要 VAG 或 HDMI * @auther TigerChain */ public interface VgaOrHdmi { /**輸出 VGA 或是 Hdmi 接口*/ String getVgaOrHdmi() ; }
2、定義源類 MiniDp
/** * 源角色,MAC 電腦上的 MINIDP 接口 * @auther TigerChain */ public class MiniDp { public String outPutMinkDp(){ return "我是 mac 上的 MiniDp 輸入接口" ; } }
3、定義適配器類 MidiDp2VgaOrHdmiAdapter
/** * 適配器,既是 MINIDP 接口也是 VAGORHDMI 接口,這樣就可以把 MINIDP 轉(zhuǎn)成 * VAG OR HDMI 接口 * @auther TigerChain */ public class MidiDp2VgaOrHdmiAdapter extends MiniDp implements VgaOrHdmi{ @Override public String getVgaOrHdmi() { return convertMiniDp2VgaOrHdmi() ; } /** * 把 MINIDP 轉(zhuǎn)化成 VAG 或 HDMI 方法 * @return */ private String convertMiniDp2VgaOrHdmi(){ //拿到源 String str = outPutMinkDp(); System.out.println(str+" 經(jīng)過(guò)適配器轉(zhuǎn)化 "); // 為這簡(jiǎn)單起見,這里直接修改源 str = "輸出變成 VGA 和 HDMI 接口" ; return str ; } }
4、定義打印機(jī)類 Projector
/** * 這是投影儀,我就是 VGA 和 HDMI 接口的 * @auther TigerChain */ public class Projector { // 我要的就是 VGA 或者 HDMI 接口 public String getVgaOrHdmi(VgaOrHdmi vgaOrHdmi){ return vgaOrHdmi.getVgaOrHdmi() ; } }
5、定義測(cè)試類 Test
/** * 測(cè)試類 * @auther TigerChain */ public class Test { public static void main(String args[]){ //投影儀 Projector projector = new Projector() ; //適配器 VgaOrHdmi adapter = new MidiDp2VgaOrHdmiAdapter() ; // 最后得到投影儀想要的 VAG or HDMI 即可 String str = projector.getVgaOrHdmi(adapter) ; System.out.println(str); } }
6、運(yùn)行查看結(jié)果
完美轉(zhuǎn)化了有木有
對(duì)象適配器實(shí)現(xiàn)上述例子
對(duì)象適配投影儀和 MAC 電腦簡(jiǎn)單的 UML
是不是和上面的圖一樣?錯(cuò),肯定不一樣,一樣我還貼出來(lái)「我又沒(méi)病」,只有一點(diǎn)改變,就是適配器不是繼承源,而是持有源的引用,代碼修改起來(lái)非常簡(jiǎn)單,只是修改適配器即可「別的代碼都是一樣的」
1、修改 MidiDp2VgaOrHdmiAdapter
/** * 適配器,既是 MINIDP 接口也是 VAGORHDMI 接口,這樣就可以把 MINIDP 轉(zhuǎn)成 * VAG OR HDMI 接口 */ public class MidiDp2VgaOrHdmiAdapter implements VgaOrHdmi{ // 修改之處 1 private MiniDp miniDp ; // 修改之處 2 public MidiDp2VgaOrHdmiAdapter(MiniDp miniDp){ this.miniDp = miniDp ; } @Override public String getVgaOrHdmi() { return convertMiniDp2VgaOrHdmi() ; } /** * 把 MINIDP 轉(zhuǎn)化成 VAG 或 HDMI 方法 * @return */ private String convertMiniDp2VgaOrHdmi(){ // 修改之處 3 拿到源 String str = miniDp.outPutMinkDp(); System.out.println(str+" 經(jīng)過(guò)適配器轉(zhuǎn)化 "); // 為這簡(jiǎn)單起見,這里直接修改源 str = "輸出變成 VGA 和 HDMI 接口" ; return str ; } }
2、修改測(cè)試類,并運(yùn)行查看結(jié)果
修改測(cè)試類
結(jié)果和上面是一樣的
適配器模式一般情況下不是軟件設(shè)計(jì)的時(shí)候就要考慮的一種模式,它是一種隨著軟件的維護(hù)可能由于不同的開發(fā)人員,不同的產(chǎn)品,不同的廠家造成的功能類似而接口不相同的情況下一種解決方案「只有碰到無(wú)法改變?cè)性O(shè)計(jì)和代碼的情況下,才考慮適配」
2、成龍初探好萊塢
我們的功夫明星成龍初闖好萊塢的時(shí)候有一個(gè)最大的障礙就是語(yǔ)言問(wèn)題「英文不太熟悉」,那么最早的時(shí)候都是有翻譯者的,那么這個(gè)翻譯員就充當(dāng)了適配器的角色「把英文翻譯成中文,或者把中文翻譯成英文」
翻譯員簡(jiǎn)單的 UML
根據(jù) UML 擼代碼
1、新建 ISpeakEn 接口
/** * Created by tigerchain on 11/12/17. */ public interface ISpeakEn { // 說(shuō)英文 String speakEnglish(String str) ; }
2、新建 ISpeakCn 接口
/** * Created by tigerchain on 11/12/17. */ public interface ISpeakCn { // 說(shuō)中文 String speakCn(String str) ; }
3、翻譯的接口「適配器」 Interpreter
/** * Created by tigerchain on 11/12/17. * 翻譯的接口 */ public interface Interpreter { // 中文翻譯成英文 void chinese2English(String str) ; // 英文翻譯成中文 void english2Chinese(String str) ; }
4、具體的翻譯員小張 ZhangTranslation
/** * Created by tigerchain on 11/12/17. * 舉個(gè)例子,成龍有一個(gè)張翻譯,能把英文翻譯成中文,也能把中文翻譯成英文 */ public class ZhangTranslation implements Iinterpreter,ISpeakCn,ISpeakEn{ @Override public void chinese2English(String str) { translationC2E(speakCn(str)); } @Override public void english2Chinese(String str) { translationE2C(str) ; } // 翻譯英文--> 中文 private void translationE2C(String str) { System.out.println("小張把 "+str+" 翻譯成中文"); } // 翻譯中文--> 英文 private void translationC2E(String str){ System.out.println("小張把 "+str+" 翻譯成英文"); } @Override public String speakCn(String str) { return str ; } @Override public String speakEnglish(String str) { return str; } }
5、來(lái)一個(gè)老外「要對(duì)話肯定要有關(guān)建人物呀」 Foreigner
/** * Created by tigerchain on 11/12/17. * 一個(gè)老外用英文給成龍打招呼 */ public class Foreigner implements ISpeakEn { @Override public String speakEnglish(String str) { String say = "Wills say:"+str ; System.out.println(say); return say ; } }
6、成龍上場(chǎng)「另一個(gè)關(guān)建人物」 JackieChan
/** * Created by tigerchain on 11/12/17. */ public class JackieChan implements ISpeakCn { @Override public String speakCn(String str) { String say = "成龍說(shuō):"+str ; System.out.println(say); return say ; } }
7、測(cè)試對(duì)話 Test
/** * Created by tigerchain on 11/12/17. * 這是一個(gè)成龍對(duì)話老外的測(cè)試類 */ public class Test { public static void main(String args[]){ // 成龍說(shuō)了一句話 JackieChan jackieChan = new JackieChan() ; String str = jackieChan.speakCn("你好 wills"); // 老外說(shuō)了一句 Foreigner foreigner = new Foreigner() ; String str2 = foreigner.speakEnglish("Hello Jackie Chain"); // 張翻譯翻譯 ZhangTranslation zhangTranslation = new ZhangTranslation() ; zhangTranslation.chinese2English(str); zhangTranslation.english2Chinese(str2); } }
8、運(yùn)行查看結(jié)果
怎么樣這個(gè)張翻譯「適配器」還不錯(cuò)吧,當(dāng)然適配器模式也會(huì)進(jìn)化,會(huì)變種,但是萬(wàn)變不離其宗「上面 Demo 就可以看作是一個(gè)變種的適配器模式」
三、Android 源碼中的適配器模式ListAdapter
沒(méi)有搞錯(cuò)吧,上一節(jié)不是說(shuō)了 ListAdapter 是一種策略模式嗎?沒(méi)錯(cuò)它也是一種適配器模式「從名字就可以看出來(lái)」
ListAdapter 適配器簡(jiǎn)單的 UML
從上圖可以看出,BaseAdapter 是一個(gè)基礎(chǔ)適配器,下面子類是具體各自的適配器,這些適配器的作用就是把數(shù)據(jù) List
以 ArrayAdapter
1、先看看 Adapter
public interface Adapter { int getCount(); Object getItem(int var1); long getItemId(int var1); boolean hasStableIds(); View getView(int var1, View var2, ViewGroup var3); int getItemViewType(int var1); int getViewTypeCount(); boolean isEmpty(); }
2、ListAdapter 繼承 Adapter 接口,所以擁有 Adapter 所有功能
3、BaseAdapter 實(shí)現(xiàn) ListAdapter 所以不僅擁有 ListAdapteer 的所有能力
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter{ //省略苦干代碼 public boolean areAllItemsEnabled() { return true; } public boolean isEnabled(int position) { return true; } public View getDropDownView(int position, View convertView, ViewGroup parent) { return getView(position, convertView, parent); } public int getItemViewType(int position) { return 0; } public int getViewTypeCount() { return 1; } public boolean isEmpty() { return getCount() == 0; } }
3、再來(lái)看看 ArrayAdapter
public class ArrayAdapterextends BaseAdapter implements Filterable, ThemedSpinnerAdapter { private List mObjects; //列出其中一個(gè)構(gòu)造方法 public ArrayAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId) { this(context, resource, textViewResourceId, new ArrayList<>()); } @Override public int getCount() { return mObjects.size(); } @Override public @Nullable T getItem(int position) { return mObjects.get(position); } public int getPosition(@Nullable T item) { return mObjects.indexOf(item); } @Override public long getItemId(int position) { return position; } @Override public @NonNull View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { return createViewFromResource(mInflater, position, convertView, parent, mResource); } //其它代碼流省略 }
我們通過(guò)源碼可以看到 ArrayAdapter
ListAdapter 既是策略模式又是適配器模式
根據(jù)選擇模式使用那種適配器 ListAdapter 就是策略模式,但是根據(jù)每個(gè)策略所實(shí)現(xiàn)功能「它就是適配器模式」
四、適配器模式的優(yōu)缺點(diǎn)優(yōu)點(diǎn)
1、客戶端只關(guān)心適配器,對(duì)客戶端來(lái)說(shuō)更簡(jiǎn)單
2、現(xiàn)有類的復(fù)用而不需要改變,解決了現(xiàn)有類和目標(biāo)類環(huán)境不一致的問(wèn)題
3、解耦「目標(biāo)類和適配器解耦」,不用改變?cè)械拇a,再一個(gè)就是某天目標(biāo)大變了,那么我們?cè)倬帉懸粋€(gè)適配器就可以了「原來(lái)的適配器可以扔掉了,就像某天你的 MAC 筆記本壞了,電源適配器就可以扔了--這是一個(gè)玩笑,除非是適配器不適用新買的 MAC」
缺點(diǎn)
1、適配器編寫過(guò)程需要多方考慮「可能會(huì)很復(fù)雜」
2、適配器把一個(gè)接口轉(zhuǎn)化成另一個(gè)接口,在客戶端會(huì)給人誤導(dǎo),明明傳入的是 A 接口,最后成 B 了,讓人很暈
到此為止,我們就介紹完了適配器模式,點(diǎn)贊是一種美德
公眾號(hào):TigerChain 更多精彩的文章等著你
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70666.html
摘要:適配器模式的結(jié)構(gòu)通過(guò)繼承實(shí)現(xiàn)通過(guò)委讓實(shí)現(xiàn)代碼實(shí)現(xiàn)目標(biāo)類使用數(shù)據(jù)線適配類使用轉(zhuǎn)適配線主函數(shù)與在適配器模式中的應(yīng)用當(dāng)前,不少公司使用整合進(jìn)行系統(tǒng)開發(fā)。 Java 23種設(shè)計(jì)模式----適配器模式 1、面向?qū)ο驩O = 面向?qū)ο蠓治鯫OA + 面向?qū)ο笤O(shè)計(jì)OOD + 面向?qū)ο缶幊蘋OP 2、編程是一門技術(shù)、同時(shí)也是一門藝術(shù) 3、應(yīng)該面向接口編程,而不是面向?qū)崿F(xiàn)編程 什么是設(shè)計(jì)模式 設(shè)計(jì)模式是...
摘要:適配器模式一適配器模式定義將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口角色目標(biāo)接口對(duì)象客戶希望的另一個(gè)接口或具體類需要適配的類現(xiàn)有的,不符合客戶需求的接口或具體類適配器對(duì)象包裝適配的對(duì)象,轉(zhuǎn)換接口實(shí)現(xiàn)方式類適配器繼承對(duì)象適配器聚合二具體實(shí)現(xiàn)創(chuàng)建目標(biāo) 適配器模式 一.適配器模式 1.1 定義 將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口. 1.2 角色 目標(biāo)接口對(duì)象(Target):客戶希望的另一個(gè)接...
摘要:建議盡量使用對(duì)象的適配器模式,少用繼承。適配器模式也是一種包裝模式,它與裝飾模式同樣具有包裝的功能,此外,對(duì)象適配器模式還具有委托的意思。 適配器模式(Adapter Pattern)屬于結(jié)構(gòu)型模式的一種,把一個(gè)類的接口變成客戶端所期待的另一種接口,從而使原本接口不匹配而無(wú)法一起工作的兩個(gè)類能夠在一起工作... 概述 當(dāng)你想使用一個(gè)已經(jīng)存在的類,而它的接口不符合你的需求,或者你想創(chuàng)建...
閱讀 3774·2021-11-11 11:00
閱讀 2244·2021-10-08 10:05
閱讀 2938·2021-10-08 10:04
閱讀 3275·2021-09-30 09:48
閱讀 3965·2021-09-27 14:10
閱讀 1781·2021-09-09 09:33
閱讀 2183·2019-08-30 15:55
閱讀 1660·2019-08-30 13:53