1. 项目结构
bash
adapter-pattern-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── adapter/
│ │ │ ├── target/
│ │ │ │ ├── MediaPlayer.java
│ │ │ │ ├── AudioPlayer.java
│ │ │ │ └── AdvancedMediaPlayer.java
│ │ │ ├── adaptee/
│ │ │ │ ├── Mp4Player.java
│ │ │ │ └── VlcPlayer.java
│ │ │ ├── adapter/
│ │ │ │ ├── MediaAdapter.java
│ │ │ │ └── AdvancedMediaAdapter.java
│ │ │ └── Main.java
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── adapter/
│ └── AdapterPatternTest.java
pom.xml
yaml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>adapter-pattern-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Adapter Pattern Demo</name>
<description>Demonstration of Adapter Design Pattern in Java</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.13.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. 代码实现
MediaPlayer.java - 目标接口
java
package com.example.adapter.target;
/**
* 目标接口:媒体播放器
* 客户端期望的接口
*/
public interface MediaPlayer {
/**
* 播放音频文件
* @param audioType 音频类型
* @param fileName 文件名
*/
void play(String audioType, String fileName);
}
AudioPlayer.java - 具体目标类
java
package com.example.adapter.target;
import com.example.adapter.adapter.MediaAdapter;
/**
* 具体目标类:音频播放器
* 实现了基本的音频播放功能
*/
public class AudioPlayer implements MediaPlayer {
private MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// 内置支持 mp3 格式
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("播放 MP3 文件: " + fileName);
}
// 使用适配器播放其他格式
else if (audioType.equalsIgnoreCase("vlc") ||
audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else {
System.out.println("不支持的媒体格式: " + audioType);
}
}
}
AdvancedMediaPlayer.java - 高级媒体播放器接口
java
package com.example.adapter.target;
/**
* 高级媒体播放器接口
* 更丰富的功能接口
*/
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
void playAvi(String fileName);
}
Mp4Player.java - MP4播放器实现
java
package com.example.adapter.adaptee;
/**
* 被适配者类:MP4播放器
* 已有的类,接口与目标接口不兼容
*/
public class Mp4Player {
public void playMp4(String fileName) {
System.out.println("播放 MP4 文件: " + fileName);
}
public void stopMp4() {
System.out.println("停止播放 MP4");
}
public void setVolume(int level) {
System.out.println("设置 MP4 音量为: " + level);
}
}
VlcPlayer.java - VLC播放器实现
java
package com.example.adapter.adaptee;
/**
* 被适配者类:VLC播放器
* 已有的类,接口与目标接口不兼容
*/
public class VlcPlayer {
public void playVlc(String fileName) {
System.out.println("播放 VLC 文件: " + fileName);
}
public void stopVlc() {
System.out.println("停止播放 VLC");
}
public void setSpeed(float speed) {
System.out.println("设置 VLC 播放速度为: " + speed);
}
}
MediaAdapter.java - 对象适配器
java
package com.example.adapter.adapter;
import com.example.adapter.adaptee.Mp4Player;
import com.example.adapter.adaptee.VlcPlayer;
import com.example.adapter.target.MediaPlayer;
/**
* 对象适配器
* 组合方式实现适配器
*/
public class MediaAdapter implements MediaPlayer {
private Mp4Player mp4Player;
private VlcPlayer vlcPlayer;
private String audioType;
public MediaAdapter(String audioType) {
this.audioType = audioType;
if (audioType.equalsIgnoreCase("mp4")) {
mp4Player = new Mp4Player();
} else if (audioType.equalsIgnoreCase("vlc")) {
vlcPlayer = new VlcPlayer();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("mp4")) {
mp4Player.playMp4(fileName);
} else if (audioType.equalsIgnoreCase("vlc")) {
vlcPlayer.playVlc(fileName);
}
}
// 额外功能:音量控制
public void setVolume(int level) {
if (audioType.equalsIgnoreCase("mp4") && mp4Player != null) {
mp4Player.setVolume(level);
}
}
}
AdvancedMediaAdapter.java - 类适配器(使用继承)
java
package com.example.adapter.adapter;
import com.example.adapter.adaptee.Mp4Player;
import com.example.adapter.target.AdvancedMediaPlayer;
/**
* 类适配器
* 继承方式实现适配器
*/
public class AdvancedMediaAdapter extends Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// 转换VLC播放逻辑到MP4播放器
System.out.println("通过适配器将VLC文件转换为MP4格式播放: " + fileName);
super.playMp4(fileName);
}
@Override
public void playMp4(String fileName) {
super.playMp4(fileName);
}
@Override
public void playAvi(String fileName) {
System.out.println("播放 AVI 文件: " + fileName);
// AVI格式的特殊处理
}
// 可以添加额外的适配方法
public void playWithSpecialEffects(String fileName) {
System.out.println("播放带特效的文件: " + fileName);
super.playMp4(fileName);
}
}
Main.java
java
package com.example.adapter;
import com.example.adapter.adapter.AdvancedMediaAdapter;
import com.example.adapter.target.AudioPlayer;
import com.example.adapter.target.MediaPlayer;
/**
* 适配器模式演示主程序
*/
public class Main {
public static void main(String[] args) {
System.out.println("=== 适配器模式演示 ===\n");
// 创建音频播放器
MediaPlayer audioPlayer = new AudioPlayer();
// 播放不同格式的文件
System.out.println("1. 播放MP3文件:");
audioPlayer.play("mp3", "song.mp3");
System.out.println("\n2. 播放MP4文件:");
audioPlayer.play("mp4", "movie.mp4");
System.out.println("\n3. 播放VLC文件:");
audioPlayer.play("vlc", "video.vlc");
System.out.println("\n4. 播放不支持格式:");
audioPlayer.play("avi", "video.avi");
System.out.println("\n=== 使用类适配器 ===");
// 使用类适配器
AdvancedMediaAdapter advancedAdapter = new AdvancedMediaAdapter();
System.out.println("\n5. 使用类适配器播放VLC文件:");
advancedAdapter.playVlc("concert.vlc");
System.out.println("\n6. 使用类适配器播放MP4文件:");
advancedAdapter.playMp4("documentary.mp4");
System.out.println("\n7. 使用类适配器播放AVI文件:");
advancedAdapter.playAvi("film.avi");
System.out.println("\n8. 使用类适配器的额外功能:");
advancedAdapter.playWithSpecialEffects("special.mp4");
// 演示适配器的额外功能
System.out.println("\n=== 演示适配器的额外功能 ===");
com.example.adapter.adapter.MediaAdapter adapter =
new com.example.adapter.adapter.MediaAdapter("mp4");
adapter.setVolume(80);
}
}
AdapterPatternTest.java
java
package com.example.adapter;
import com.example.adapter.target.AudioPlayer;
import com.example.adapter.target.MediaPlayer;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.junit.Assert.assertTrue;
public class AdapterPatternTest {
@Test
public void testAudioPlayerWithMp3() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
MediaPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "test.mp3");
System.setOut(originalOut);
assertTrue(outContent.toString().contains("播放 MP3 文件: test.mp3"));
}
@Test
public void testAudioPlayerWithMp4() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
MediaPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp4", "test.mp4");
System.setOut(originalOut);
assertTrue(outContent.toString().contains("播放 MP4 文件: test.mp4"));
}
@Test
public void testAudioPlayerWithUnsupportedFormat() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream originalOut = System.out;
System.setOut(new PrintStream(outContent));
MediaPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("avi", "test.avi");
System.setOut(originalOut);
assertTrue(outContent.toString().contains("不支持的媒体格式: avi"));
}
}
3. 构建和运行
构建项目
bash
# 在项目根目录执行
mvn clean compile
运行主程序
bash
mvn exec:java -Dexec.mainClass="com.example.adapter.Main"
运行测试
bash
mvn test
打包项目
bash
mvn package
4. 核心概念
-
适配器模式的三种实现方式:
-
对象适配器:使用组合方式(MediaAdapter)
-
类适配器:使用继承方式(AdvancedMediaAdapter)
-
-
适配器模式的优点:
-
让原本不兼容的接口可以协同工作
-
提高了类的复用性
-
增加了类的透明度
-
灵活性好
-
-
适用场景:
-
需要使用现有类,但其接口不符合需求
-
想要创建一个可以复用的类,与不相关或不可预见的类协同工作
-
需要使用多个现有的子类,但为每个子类适配接口不现实
-