java设计模式—适配器模式
## 适配器模式
适配器模式是设计模式中的一种,属于结构型模式。这个模式的主要目标是使得原本不兼容的接口能够相互合作。
就像现实生活中的电源适配器一样,可以使得不同的电源插头可以在不同的电源插座上使用。
## 主要解决的问题
在软件开发过程中,经常会遇到两个已有的类,它们的功能满足我们的需求,但是它们的接口并不兼容。
如果直接修改这两个类的源代码,可能会引入新的错误,或者破坏已有的测试。
在这种情况下,我们可以使用适配器模式,来提供一个能够调和这两个类接口差异的解决方案。
## 何时使用适配器模式
- 你想使用一个已经存在的类,但是它的接口不符合你的需求。
- 你想创建一个可以复用的类,该类可以与其他不相关的类或者不可预见的类(即那些接口可能不一定兼容的类)协同工作。
- 你需要使用几个已有的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父接口。
## 举一个生活中的例子
想象你去了一个外国国家,你带了一个电动剃须刀,但是你发现那个国家的电源插头和你的剃须刀插头不兼容。这时,你需要一个电源适配器,它一头适配你的剃须刀插头,另一头适配那个国家的电源插座。
在这个例子中,电源适配器就扮演了“适配器”的角色。
## 优点
- 提高了类的复用性。
- 增加了类的透明度。
- 灵活性好。
## 缺点
- 过多地使用适配器,会使系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统的复杂性往往来自于这些难以直视的细节。
## 使用场景
在软件系统中,当你想使用某个类,但是它的接口不符合你的需求,或者你想创建一个可以复用的类,该类可以与其他不相关或不可预见的类协同工作,那么可以使用适配器模式。
## 代码示例
假设有一个MediaPlayer接口和一个更高级的AdvancedMediaPlayer接口。我们想要让MediaPlayer可以播放更高级的音频,但是我们不想改变现有的类,所以我们创建了一个适配器。
````
// 媒体播放器接口
public interface MediaPlayer {
void play(String audioType, String fileName);
}
// 高级媒体播放器接口
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
// 创建实现了 AdvancedMediaPlayer 接口的实体类。
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}
@Override
public void playMp4(String fileName) {
//do nothing
}
}
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
//do nothing
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}
// 创建适配器类,实现 MediaPlayer 接口
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType){
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
}else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}
// 创建实现了 MediaPlayer 接口的实体类。
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// 播放 mp3 音乐文件的内置支持
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: " + fileName);
}
// mediaAdapter 提供了播放其他文件格式的支持
else if(audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}
````
在这个例子中,AudioPlayer通过使用MediaAdapter适配器类,可以播放mp3、mp4和vlc格式的音频,而不需要直接实现AdvancedMediaPlayer接口。