適配器模式的應用
適配器模式
在計算機編程中,適配器模式(有時候也稱包裝樣式或者包裝)將一個類的接口適配成用戶所期待的。一個適配允許通常因為接口不兼容而不能在一起工作的類工作在一起,做法是將類自己的接口包裹在一個已存在的類中。
下面是類適配器的UML圖:
(2)對象適配器:
對象適配器”通過組合除了滿足“用戶期待接口”還降低了代碼間的不良耦合。在工作中推薦使用“對象適配”。下面是對象適配器的UML圖:
(3) 缺省適配器模式:
缺省適配器模式是一種特殊的適配器模式,但這個適配器是由一個抽象類實現的,并且在抽象類中要實現目標接口中所規定的所有方法,但很多方法的實現都是“平庸”的實現,也就是說,這些方法都是空方法。而具體的子類都要繼承此抽象類。
一 概述
定義:適配器模式將某個類的接口轉換成客戶端期望的另一個接口表示,主的目的是兼容性,讓原本因接口不匹配不能一起工作的兩個類可以協同工作。其別名為包裝器(Wrapper)。
屬于結構型模式
主要分為三類:類適配器模式、對象的適配器模式、接口的適配器模式。
本文定義:
需要被適配的類、接口、對象(我們有的),簡稱 src(source)
最終需要的輸出(我們想要的),簡稱 dst (destination,即Target)
適配器稱之為 Adapter 。
一句話描述適配器模式的感覺: src-》Adapter-》dst,即src以某種形式(三種形式分別對應三種適配器模式)給到Adapter里,最終轉化成了dst。
拿我們Android開發最熟悉的展示列表數據的三大控件:ListView,GridView,RecyclerView的Adapter來說,它們三個控件需要的是View(dst),而我們有的一般是datas(src),所以適配器Adapter就是完成了數據源datas 轉化成 ItemView的工作。
帶入src-》Adapter-》dst中,即datas-》Adapter-》View.
使用場景:
1 系統需要使用現有的類,而這些類的接口不符合系統的需要。
2 想要建立一個可以重復使用的類,用于與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
3 需要一個統一的輸出接口,而輸入端的類型不可預知。
二 類適配器模式:
一句話描述:Adapter類,通過繼承 src類,實現 dst 類接口,完成src-》dst的適配。
別的文章都用生活中充電器的例子來講解適配器,的確,這是個極佳的舉例,本文也不能免俗:
充電器本身相當于Adapter,220V交流電相當于src,我們的目dst標是5V直流電。
我們現有的src類:
public class Voltage220 {
public int output220V() {
int src = 220;
System.out.println(“我是” + src + “V”);
return src;
}
}1234567891011121314
我們想要的dst接口:
public interface Voltage5 {
int output5V();
}
1234567891011
適配器類:
public class VoltageAdapter extends Voltage220 implements Voltage5 {
@Override
public int output5V() {
int src = output220V();
System.out.println(“適配器工作開始適配電壓”);
int dst = src / 44;
System.out.println(“適配完成后輸出電壓:” + dst);
return dst;
}
}123456789101112131415161718
Client類:
public class Mobile {
/**
* 充電方法
*
* @param voltage5
*/
public void charging(Voltage5 voltage5) {
if (voltage5.output5V() == 5) {
System.out.println(“電壓剛剛好5V,開始充電”);
} else if (voltage5.output5V() 》 5) {
System.out.println(“電壓超過5V,都閃開 我要變成note7了”);
}
}
}123456789101112131415161718192021
測試代碼:
System.out.println(“===============類適配器==============”);
Mobile mobile = new Mobile();
mobile.charging(new VoltageAdapter());123
輸出:
===============類適配器==============
我是220V
適配器工作開始適配電壓
適配完成后輸出電壓:5
電壓剛剛好5V,開始充電12345
類圖如下:
小結:
Java這種單繼承的機制,所有需要繼承的我個人都不太喜歡。
所以類適配器需要繼承src類這一點算是一個缺點,
因為這要求dst必須是接口,有一定局限性;
且src類的方法在Adapter中都會暴露出來,也增加了使用的成本。
但同樣由于其繼承了src類,所以它可以根據需求重寫src類的方法,使得Adapter的靈活性增強了。
三 對象適配器模式(常用):
基本思路和類的適配器模式相同,只是將Adapter類作修改,這次不繼承src類,而是持有src類的實例,以解決兼容性的問題。
即:持有 src類,實現 dst 類接口,完成src-》dst的適配。
(根據“合成復用原則”,在系統中盡量使用關聯關系來替代繼承關系,因此大部分結構型模式都是對象結構型模式。)
Adapter類如下:
public class VoltageAdapter2 implements Voltage5 {
private Voltage220 mVoltage220;
public VoltageAdapter2(Voltage220 voltage220) {
mVoltage220 = voltage220;
}
@Override
public int output5V() {
int dst = 0;
if (null != mVoltage220) {
int src = mVoltage220.output220V();
System.out.println(“對象適配器工作,開始適配電壓”);
dst = src / 44;
System.out.println(“適配完成后輸出電壓:” + dst);
}
return dst;
}
}123456789101112131415161718192021222324252627
測試代碼:
System.out.println(“\n===============對象適配器==============”);
VoltageAdapter2 voltageAdapter2 = new VoltageAdapter2(new Voltage220());
Mobile mobile2 = new Mobile();
mobile2.charging(voltageAdapter2);1234
輸出:
===============對象適配器==============
我是220V
對象適配器工作,開始適配電壓
適配完成后輸出電壓:5
電壓剛剛好5V,開始充電12345
類圖:
小結:
對象適配器和類適配器其實算是同一種思想,只不過實現方式不同。
根據合成復用原則,組合大于繼承,
所以它解決了類適配器必須繼承src的局限性問題,也不再強求dst必須是接口。
同樣的它使用成本更低,更靈活。
(和裝飾者模式初學時可能會弄混,這里要搞清,裝飾者是對src的裝飾,使用者毫無察覺到src已經被裝飾了(使用者用法不變)。 這里對象適配以后,使用者的用法還是變的。
即,裝飾者用法: setSrc-》setSrc,對象適配器用法:setSrc-》setAdapter.)
四 接口適配器模式
也有文獻稱之為認適配器模式(Default Adapter Pattern)或缺省適配器模式。
定義:
當不需要全部實現接口提供的方法時,可先設計一個抽象類實現接口,并為該接口中每個方法提供一個默認實現(空方法),那么該抽象類的子類可有選擇地覆蓋父類的某些方法來實現需求,它適用于一個接口不想使用其所有的方法的情況。
我們直接進入大家最喜愛的源碼撐腰環節:
源碼撐腰環節:
Android中的屬性動畫ValueAnimator類可以通過addListener(AnimatorListener listener)方法添加監聽器,
那么常規寫法如下:
ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100);
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
valueAnimator.start();1234567891011121314151617181920212223
有時候我們不想實現Animator.AnimatorListener接口的全部方法,我們只想監聽onAnimationStart,我們會如下寫:
ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100);
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
//xxxx具體實現
}
});
valueAnimator.start();12345678
顯然,這個AnimatorListenerAdapter類,就是一個接口適配器。
查看該Adapter類源碼:
public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,
Animator.AnimatorPauseListener {
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
}1234567891011121314151617181920212223242526
可見,它空實現了Animator.AnimatorListener類(src)的所有方法。
對應的src類:
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}123456789
類圖:
我們程序里的匿名內部類就是Listener1 2 這種具體實現類。
new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
//xxxx具體實現
}
}123456
接口適配器模式很好理解,令我們的程序更加簡潔明了。
五 總結
我個人理解,三種命名方式,是根據 src是以怎樣的形式給到Adapter(在Adapter里的形式)來命名的。
類適配器,以類給到,在Adapter里,就是將src當做類,繼承,
對象適配器,以對象給到,在Adapter里,將src作為一個對象,持有。
接口適配器,以接口給到,在Adapter里,將src作為一個接口,實現。
Adapter模式最大的作用還是將原本不兼容的接口融合在一起工作。
但是在實際開發中,實現起來不拘泥于本文介紹的三種經典形式,
例如Android中ListView、GridView的適配器Adapter,就不是以上三種經典形式之一,
我個人理解其屬于對象適配器模式,一般日常使用中,我們都是在Adapter里持有datas,然后通過getView()/onCreateViewHolder()方法向ListView/RecyclerView提供View/ViewHolder。
Client是Lv Gv Rv ,它們是顯示View的類。
所以dst(Target)是View。
一般來說我們有的src是數據datas,
即,我們希望:datas(src)-》Adapter-》View(dst)-》Rv(Client)。
非常好我支持^.^
(0) 0%
不好我反對
(0) 0%
相關閱讀:
- [電子說] ZS2934SL-24W電源適配器方案 2023-10-24
- [電子說] 小體積也有大乾坤!高效又緊湊的的5W USB電源適配器方案 2023-10-24
- [電子說] 小體積也有大乾坤!高效又緊湊的的5W USB電源適配器方案 2023-10-24
- [電子說] 【大大芯方案】極速快充,大聯大推出基于onsemi產品的240W PD3.1適配器方案 2023-10-20
- [電子說] AS7202眾享次級側同步整流器回程轉換器集成了超低導通狀態電阻45V功率MOSFET 2023-10-17
- [電子說] AS7201眾享次級側同步整流器回程轉換器 2023-10-17
- [電子說] 六級能效新選擇!解鎖一份高效率低功耗的5V2A充電器方案~ 2023-10-17
- [模擬技術] 二極管OR連接示例 2023-10-17
( 發表人:龔婷 )