设计模式之适配器模式

1、角色划分

  • Target:目标抽象类
  • Adapter:适配器类
  • Adaptee:适配者类
  • Client:客户类


2、UML类图



3、源码

public class AdaptorPattern {

    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        audioPlayer.play("mp3", "beyond the horizon.mp3");
        audioPlayer.play("mp4", "alone.mp4");
        audioPlayer.play("rmvb", "far far away.rmvb");
        audioPlayer.play("avi", "mind me.avi");
    }
}

/**
 * 普通的媒体播放器
 */
interface MediaPlayer {
    void play(String audioType,String fileName);
}

/**
 * 高级的媒体播放器
 */
interface AdvancedMediaPlayer {
    void playRmvb(String fileName);
    void playAvi(String fileName);
}

/**
 * 可以播放rmvb格式的播放器
 */
class RmvbPlayer implements AdvancedMediaPlayer {
    public void playRmvb(String fileName) {
        System.out.println("Playing rmvb file. Name: " + fileName);
    }
    public void playAvi(String fileName) {

    }
}

/**
 * 可以播放avi格式的播放器
 */
class AviPlayer implements AdvancedMediaPlayer {
    public void playRmvb(String fileName) {

    }
    public void playAvi(String fileName) {
        System.out.println("Playing avi file. Name: " + fileName);
    }
}

/**
 * 创建实现了 MediaPlayer 接口的适配器类。
 */
class MediaAdapter implements MediaPlayer {
    private AdvancedMediaPlayer advancedMediaPlayer;
    public MediaAdapter(String audioType) {
        if("RMVB".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer = new RmvbPlayer();
        } else if("AVI".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer = new AviPlayer();
        }
    }

    public void play(String audioType, String fileName) {
        if("RMVB".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer.playRmvb(fileName);
        } else if("AVI".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer.playAvi(fileName);
        }
    }
}

/**
 * 创建实现了 MediaPlayer 接口的实体类。
 */
class AudioPlayer implements MediaPlayer {

    private MediaAdapter mediaAdapter;
    public void play(String audioType, String fileName) {
        if("MP4".equalsIgnoreCase(audioType)) {
            System.out.println("Playing mp4 file. Name: " + fileName);
        } else if("RMVB".equalsIgnoreCase(audioType) || "AVI".equalsIgnoreCase(audioType)) {
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        } else{
            System.out.println("media is not support");
        }

    }
}

输出结果

media is not support
Playing mp4 file. Name: alone.mp4
Playing rmvb file. Name: far far away.rmvb
Playing avi file. Name: mind me.avi


3、特点

在类适配器模式中,适配器类实现了目标抽象类接口并继承了适配者类,并在目标抽象类的实现方法中调用所继承的适配者类的方法;在对象适配器模式中,适配器类继承了目标抽象类并定义了一个适配者类的对象实例,在所继承的目标抽象类方法中调用适配者类的相应业务方法


4、优点

  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
  • 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。


5、缺点

对于Java不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。


6、jdk中的适配器模式

  • InputStreamReader   Client
  • StreamDecoder         Adapter
  • InputStream              Adaptee
  • Reader                      Target
// 该类为Client类
public class InputStreamReader extends Reader {
    // 这里的sd为适配器类
    private final StreamDecoder sd;    

    // 通过构造方法实例化Adapter
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }

    // target的抽象方法
	public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length);
    }

    ...
}

// 该类为Adapter类
public class StreamDecoder extends Reader {
    private InputStream in;

	// target的抽象read方法
    public int read() throws IOException {
        return this.read0();
    }
    
    read0方法中最后还是会调用readBytes,完成字节流的读取

    // 给inputstreamreader添加可以读取bytes的方法,适配了Adaptee的read方法
    private int readBytes() throws IOException {
        	...
                int var4 = this.in.read(this.bb.array(), this.bb.arrayOffset() + var2, var3);
            ...
    }
}

// 该类为Target类
public abstract class Reader implements Readable, Closeable {
	// 抽象方法
	abstract public int read(char cbuf[], int off, int len) throws IOException;
}

// 该类为Adaptee类
public abstract class InputStream implements Closeable {
	// Adaptee的read方法
	public int read(byte b[], int off, int len) throws IOException {
       ...
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值