设计模式学习笔记(九)适配器模式

设计模式学习笔记(九)适配器模式

概念

适配器模式是一种常用的设计模式,它用于将一个类的接口转换成客户端所期望的另一种接口。适配器模式可以让原本由于接口不兼容而不能一起工作的类们能够协同工作,它通过一个适配器类来连接客户端和被适配的类。

比如:当业务类想要调用工具类的getDate方法,业务中已经写了此方法,而且工具类没有getDate方法,那么如果我们想增加一个工具类,就需要中间加一个适配器,用来将业务类想调用的新的工具类联系起来。
在这里插入图片描述
适配器模式有三个主要角色:
● Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
● Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
● Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

适配器模式的核心思想是通过适配器来包装被适配者,使得客户端可以通过目标接口与被适配者进行交互。适配器会将客户端的请求转换为被适配者可以理解的形式,并将被适配者的响应转换为客户端可以接受的形式。

上述例子中,业务类指的就是目标抽象类,新的工具类值的是适配者类,通过适配器类将两者联系起来,在对象适配器模式中,适配器与适配者之间是关联关系;在类适配器模式中,适配器与适配者之间是继承(或实现)关系。在实际开发中,对象适配器的使用频率更高

示例

对象适配器模式: 对象适配器模式使用组合关系来实现适配器。适配器类持有一个被适配者对象的引用,并实现目标接口。当调用目标接口的方法时,适配器会委托给被适配者对象进行实际的操作。
优点:是可以适配多个被适配者对象,因为适配器与被适配者对象之间是动态关联的。
类适配器模式: 类适配器模式使用多重继承来实现适配器。适配器类同时继承目标接口(Target Interface)和被适配者(Adaptee),从而让适配器具备了目标接口的行为,并能调用被适配者的方法。使用类适配器模式时,适配器可以通过重写目标接口的方法并在其中调用被适配者的方法来完成适配。
优点:是能够重写目标接口的方法,以便更好地适应客户端的需求。然而
缺点:适配器只能适配一个被适配者类,因为继承是静态的,适配器与被适配者类之间是编译时的关系。

示例1 对象适配器

假如当前有一个音乐播放器,它只能播放mq3类的音乐,但是现在的文件格式都是flac文件,因此我们需要在不修改源代码的情况下,使用一个适配器将其他类型的音乐转换为mp3并进行播放。

1、首先我们定义业务类,可以是抽象类也可以是接口或实现类

/**
 * 目标抽象类:业务类
 * 在此类中调用播放音乐功能
 * */
public interface MediaPlayer {
    public String mp3ToStream(String path);    //将mp3文件路径转换为文件流
}

2、定义适配者类,此类用于对接目标抽象类的mp3ToStream方法

/**
 * 适配者类
 * 目标抽象类想要调用的方法
 * */
public class FlacToMp3 {
    public String fileToStream(String path) {
        path.replaceAll("mp3","flac");
        return path + "路径下的flac文件转换成mp3文件流";
    }
}

3、定义适配器,实现1目标抽象类,用于将1中的目标抽象类与2中的适配者类联系

/**
 * 适配器类:将抽象目标类本来想调用的mp3转文件流的方法,
 * 通过此类转换为适配器类FlacToMp3中的flac转文件流方法
 * */
public class OperationAdapter implements MediaPlayer {
    FlacToMp3 flacToMp3 = new FlacToMp3();
    @Override
    public String mp3ToStream(String path) {
        return flacToMp3.fileToStream(path);
    }
}

4、客户端进行测试

 		String path = "xxxx/xxxx/xxx.mp3";
        MediaPlayer oa = new OperationAdapter();
        String fileStream = oa.mp3ToStream(path);
        System.out.println(fileStream);

输出结果

xxxx/xxxx/xxx.mp3路径下的flac文件转换成mp3文件流

示例1 类适配器

我们将适配器中对象方式调用被适配者的方法,改为通过集成被适配者类的方法来调用

/**
 * 适配器类:将抽象目标类本来想调用的mp3转文件流的方法,
 * 通过此类转换为适配器类FlacToMp3中的flac转文件流方法
 * */
public class OperationAdapterObject extends FlacToMp3 implements MediaPlayer {
    @Override
    public String mp3ToStream(String path) {
        return this.fileToStream(path);
    }
}

缺省适配器

缺省适配器模式(Default Adapter Pattern)是适配器模式的一种变体,也称为适配器接口默认实现。它提供了一个中间抽象类或接口,其中包含了目标接口的所有方法的默认实现,从而使得子类只需要继承该缺省适配器类并覆盖自己感兴趣的方法即可,无需实现目标接口的所有方法。

缺省适配器模式主要用于解决以下问题:

当目标接口有多个方法,但我们只关心其中一部分方法时,可以通过继承缺省适配器类并重写感兴趣的方法,避免实现不必要的方法。
当需要对目标接口进行扩展时,可以通过修改缺省适配器类来添加新的默认实现方法,而无需修改所有的子类。
在这里插入图片描述
● ServiceInterface(适配者接口):它是一个接口,通常在该接口中声明了大量的方法。
● AbstractServiceClass(缺省适配器类):它是缺省适配器模式的核心类,使用空方法的形式实现了在ServiceInterface接口中声明的方法。通常将它定义为抽象类,因为对它进行实例化没有任何意义。
● ConcreteServiceClass(具体业务类):它是缺省适配器类的子类,在没有引入适配器之前,它需要实现适配者接口,因此需要实现在适配者接口中定义的所有方法,而对于一些无须使用的方法也不得不提供空实现。在有了缺省适配器之后,可以直接继承该适配器类,根据需要有选择性地覆盖在适配器类中定义的方法。
示例:
1、目标抽象类

/**
 * 目标抽象类:业务类
 * 在此类中调用播放音乐功能
 * */
public interface MediaPlayer {
    public String mp3ToStream(String path);    //将mp3文件路径转换为文件流
    public String mp4ToStream(String path);    //将mp4文件路径转换为文件流
    public String avgToStream(String path);    //将avg文件路径转换为文件流
}

2、如果我们只想实现目标抽象类的第一个方法mp3ToStream,那么我们就创建一个抽象类实现上类

abstract class MediaPlayerImpl implements MediaPlayer {
    @Override
    public String mp3ToStream(String path) {
        return "xxx";
    }
    @Override
    public abstract String mp4ToStream(String path);    //将mp4文件路径转换为文件流
    @Override
    public abstract String avgToStream(String path);    //将avg文件路径转换为文件流
}

总结

优点:
1、适配器模式可以让已有的类与其他类协同工作,无需修改原有代码,提高代码的可重用性。
2、可以封装复杂的转换过程,对客户端隐藏具体的实现细节。
3、可以通过引入适配器,实现类与接口之间的解耦,提高系统的扩展性和灵活性。

缺点:
1、增加了额外的代码量,引入了适配器对象的间接性,增加了代码的复杂性。
2、在适配器转换过程中,可能会导致性能损失。
3、如果需要适配的接口发生变化,适配器本身也需要进行相应的修改。

适用场景:
1、当需要使用一个已经存在的类,但其接口不符合需求时,可以使用适配器模式。
2、当希望复用一些现存的类,但是接口与系统要求不一致时,可以使用适配器模式。
3、当需要建立一个可复用的类,该类可以与多个不相关的或不可预见的类进行协作时,可以使用适配器模式。
4、当希望通过一个统一的接口与多个类交互时,可以使用适配器模式。

总之,适配器模式能够通过引入适配器对象来实现接口的转换,使得原本不兼容的类能够协同工作。它在软件开发中具有广泛的应用场景,能够提高代码的可重用性和灵活性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值