Java設(shè)計(jì)模式-適配器模式
什么是適配器模式
適配器模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,它的主要作用是使得原本不兼容的接口可以一起工作。適配器模式通過(guò)創(chuàng)建一個(gè)包裝類,將一個(gè)類的接口轉(zhuǎn)換成客戶期望的另一個(gè)接口。
主要解決什么問(wèn)題
適配器模式主要解決的是在軟件系統(tǒng)中,經(jīng)常會(huì)遇到現(xiàn)有的類無(wú)法直接滿足新的需求,需要使用一個(gè)已經(jīng)存在的接口,但是這個(gè)接口又與現(xiàn)有的代碼不兼容的問(wèn)題。
在什么時(shí)候我們需要使用適配器模式
當(dāng)我們需要使用一個(gè)已經(jīng)存在的類,而它的接口不符合我們的需求,或者我們希望創(chuàng)建一個(gè)可以復(fù)用的類,該類可以與其他不相關(guān)的類或者不可預(yù)見的類(即那些接口可能不一定兼容的類)協(xié)同工作時(shí),我們可以使用適配器模式。
生活中的應(yīng)用實(shí)例
生活中的一個(gè)常見例子就是電源適配器。比如,你的手機(jī)可能使用USB-C接口進(jìn)行充電,但是你的電源插座可能只有標(biāo)準(zhǔn)的美式或歐式插孔。在這種情況下,你需要一個(gè)電源適配器,將電源插座的接口轉(zhuǎn)換為USB-C接口,使得你的手機(jī)可以進(jìn)行充電。
優(yōu)點(diǎn)
可以讓任何兩個(gè)沒有關(guān)聯(lián)的類一起運(yùn)行。
提高了類的復(fù)用性。
增加了類的透明度。
缺點(diǎn)
過(guò)多地使用適配器,會(huì)使系統(tǒng)非常零亂,不易整體進(jìn)行把握。
由于Java至多繼承一個(gè)類,所以至多只能適配一個(gè)適配者類,而且目標(biāo)類必須是抽象類。
使用場(chǎng)景
系統(tǒng)需要使用現(xiàn)有的類,而這些類的接口不符合系統(tǒng)的需求。
想要建立一個(gè)可復(fù)用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些未來(lái)可能存在的類一起工作。
代碼示例
假設(shè)我們有一個(gè) MediaPlayer 接口,但是我們有一個(gè) VlcPlayer 類只實(shí)現(xiàn)了 AdvancedMediaPlayer 接口。我們可以創(chuàng)建一個(gè)適配器 MediaAdapter 來(lái)使得 VlcPlayer 可以被 MediaPlayer 接口使用。
interface MediaPlayer {
? ? void play(String audioType, String fileName);
}
interface AdvancedMediaPlayer {
? ? void playVlc(String fileName);
}
class VlcPlayer implements AdvancedMediaPlayer {
? ? @Override
? ? public void playVlc(String fileName) {
? ? ? ? System.out.println("Playing vlc file. Name: " + fileName);
? ? }
}
class MediaAdapter implements MediaPlayer {
? ? AdvancedMediaPlayer advancedMediaPlayer;
? ? public MediaAdapter(String audioType) {
? ? ? ? if (audioType.equalsIgnoreCase("vlc")) {
? ? ? ? ? ? advancedMediaPlayer = new VlcPlayer();
? ? ? ? }
? ? }
? ? @Override
? ? public void play(String audioType, String fileName) {
? ? ? ? if (audioType.equalsIgnoreCase("vlc")) {
? ? ? ? ? ? advancedMediaPlayer.playVlc(fileName);
? ? ? ? }
? ? }
}
class AudioPlayer implements MediaPlayer {
? ? MediaAdapter mediaAdapter;
? ? @Override
? ? public void play(String audioType, String fileName) {
? ? ? ? if (audioType.equalsIgnoreCase("vlc")) {
? ? ? ? ? ? mediaAdapter = new MediaAdapter(audioType);
? ? ? ? ? ? mediaAdapter.play(audioType, fileName);
? ? ? ? } else {
? ? ? ? ? ? System.out.println("Invalid media. " + audioType + " format not supported");
? ? ? ? }
? ? }
}
在這個(gè)例子中,AudioPlayer 使用 MediaAdapter 適配 VlcPlayer,使得 AudioPlayer 可以播放VLC格式的文件,而無(wú)需修改 VlcPlayer 類。