结构型-适配器模式

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)

  • 适配器模式的优点:

    • 让原本不兼容的接口可以协同工作

    • 提高了类的复用性

    • 增加了类的透明度

    • 灵活性好

  • 适用场景:

    • 需要使用现有类,但其接口不符合需求

    • 想要创建一个可以复用的类,与不相关或不可预见的类协同工作

    • 需要使用多个现有的子类,但为每个子类适配接口不现实

相关推荐
老朱佩琪!7 天前
Unity适配器模式
unity·设计模式·游戏引擎·适配器模式
有一个好名字8 天前
设计模式-适配器模式
设计模式·适配器模式
ZouZou老师16 天前
C++设计模式之适配器模式:以家具生产为例
java·设计模式·适配器模式
咨询QQ:48773927820 天前
一款基于.NET Core Web + Bootstrap的企业级快速后台开发框架。 内置模块如
适配器模式
雨中飘荡的记忆23 天前
设计模式之适配器模式详解
java·设计模式·适配器模式
口袋物联1 个月前
设计模式之适配器模式在 C 语言中的应用(含 Linux 内核实例)
c语言·设计模式·适配器模式
明洞日记1 个月前
【设计模式手册008】适配器模式 - 让不兼容的接口协同工作
java·设计模式·适配器模式
老鼠只爱大米1 个月前
Java 设计模式之适配器模式:系统集成的万能接口
java·设计模式·适配器模式·adapter·java设计模式
小毛驴8501 个月前
软件设计模式-适配器模式
电脑·适配器模式