【Kotlin设计模式】Kotlin实现适配器模式

前言

适配器模式(Adapter Pattern)的核心将某个类的接口转换成客户端期望的另一个接口表示,使得客户端能够通过自己期望的接口与不兼容的类进行交互。适配器模式有三种实现方式,分别是类适配器模式对象适配器模式接口适配器模式

我们假设有个视频输出盒子,当前只能接收和输出HDMI信号,现在客户的输入设备只能输出VGA信号,则我们可以通过转换器(要适配的类),将VGA信号转换成HDMI信号做输出。

实现

1、类适配器模式

客户目标接口,客户的新设备只能输出VGA信号,无法输出HDMI信号。

kotlin 复制代码
/**
 * 客户目标输入接口
 */
interface SourceInput {
    fun inputVGA(signal:String)
}

Modem盒子只接收且输出HDMI信号,调制后输出给到显示设备进行显示。

kotlin 复制代码
/**
 * 要适配的类
 */
open class ModemOutput {
    fun outputHDMI(signal:String){
        println("设备输出${signal}给显示设备")
    }
}

新的输入设备输出VGA模拟信号不满足现在的需求,我们通过定义转换器OutputAdapter,将VGA模拟信号转化成HDMI数字信号进行输出到Modem盒子中。

kotlin 复制代码
/**
 * 转换器
 */
class OutputAdapter : ModemOutput(), SourceInput {

    override fun inputVGA(signal: String) {
        if ("VGA模拟信号" == signal) {
            println("【转HDMI信号转换器】>> 接收到了源设备,输入的${signal}")
            val digital = convertVGAToHDMI(signal)
            outputHDMI(digital)
        } else {
            throw IllegalArgumentException("输入信号错误")
        }
    }

    private fun convertVGAToHDMI(signal: String): String {
        println("【转HDMI信号转换器】>> 转化器将${signal}转化成HDMI数字信号")
        return "HDMI数字信号"
    }
}

客户端

kotlin 复制代码
val adapter = OutputAdapter() as SourceInput
adapter.inputVGA("VGA模拟信号")

// 【转HDMI信号转换器】>> 接收到了源设备,输入的VGA模拟信号
// 【转HDMI信号转换器】>> VGA转HDMI转化器将VGA模拟信号转化成HDMI数字信号
//  设备输出HDMI数字信号给显示设备

适配器类需要继承ModemOutputJava是单继承模式,所以目标文件必须要是接口。

2、对象适配器模式

对象适配器模式较类适配器模式相比,原来的适配器不再继承要适配的类,将其作为适配器的构造参数传入,把继承解耦。

kotlin 复制代码
/**
 * 要适配的类
 */
open class ModemOutput {
    fun outputHDMI(signal:String){
        println("设备输出${signal}给显示设备")
    }
}
kotlin 复制代码
/**
 * 目标接口
 */
interface SourceInput {
    fun inputVGA(signal:String)
}
kotlin 复制代码
/**
 * 转换器
 */
class OutputAdapter(output: ModemOutput) : SourceInput {

    private var mOutput:ModemOutput = output

    override fun inputVGA(signal: String) {
        if ("VGA模拟信号" == signal) {
            println("【转HDMI信号转换器】>> 接收到了源设备,输入的${signal}")
            val digital = convertVGAToHDMI(analog)
            mOutput.outputHDMI(signal)
        } else {
            throw IllegalArgumentException("输入信号错误")
        }
    }

    private fun convertVGAToHDMI(signal: String): String {
        println("【转HDMI信号转换器】>> VGA转HDMI转化器将${signal}转化成HDMI数字信号")
        return "HDMI数字信号"
    }

}

3、接口适配器模式

接口适配器模式适用于目标接口中有多个方法,上面我们举了个目标接口中输入VGA的例子,假如还有DP接口DVI接口的输入,适配器类在实现目标接口时候就要都实现其他的方法,但是客户端输入只有一种,不需要实现全部接口时,如果适配器定义抽象类来实现接口,并且接口中方法空实现,可以灵活解决这个问题。

目标接口新增格式信源输入方法,要适配的类不变。

kotlin 复制代码
/**
 * 目标接口
 */
interface SourceInput {
    fun inputVGA(signal:String)
    fun inputDP(signal:String)
    fun inputDVI(signal:String)
}
kotlin 复制代码
/**
 * 要适配的类
 */
open class ModemOutput {
    fun outputHDMI(signal:String){
        println("设备输出${signal}给显示设备")
    }
}

新增抽象类,继承源文件ModemOutput、实现目标接口,覆写空方法,不做具体实现。

kotlin 复制代码
abstract class OutputAdapter:ModemOutput(),SourceInput {

    override fun inputDP(signal: String) {
        TODO("Not yet implemented")
    }

    override fun inputDVI(signal: String) {
        TODO("Not yet implemented")
    }

    override fun inputVGA(signal: String) {
        TODO("Not yet implemented")
    }
}

客户端只根据自己需要的,具体实现信号输入方法。

kotlin 复制代码
val adapter = object : OutputAdapter() {
         override fun inputDVI(signal: String) {
             super.inputDVI(signal)
             println("【转HDMI信号转换器】>> 接收到了源设备,输入的${signal}")
             val digital = convertSignalToHDMI(signal)
             outputHDMI(digital)
         }
     }


 private fun convertSignalToHDMI(signal: String): String {
     when (signal) {
         "VGA信号" -> {
             println("【转HDMI信号转换器】>> 转HDMI转化器将${signal}转化成HDMI数字信号")
         }
         "DP信号" -> {
             println("【转HDMI信号转换器】>> 转HDMI转化器将${signal}转化成HDMI数字信号")
         }
         "DVI信号" -> {
             println("【转HDMI信号转换器】>> 转HDMI转化器将${signal}转化成HDMI数字信号")
         }
         else ->{
             throw IllegalArgumentException("输入信号格式不支持")
         }
     }
     return "HDMI数字信号"
 }
 

总结

适配器模式可以以类适配器或对象适配器的形式实现,灵活性高。类适配器使用多重继承(在Java中通过接口实现),对象适配器通过组合来实现,原本由于接口不兼容而无法一起工作的类可以协同工作,从而提高了代码的复用性,允许通过引入新的适配器来适应新需求,而无需修改现有的代码,从而实现了开闭原则。

相关推荐
闲人一枚(学习中)31 分钟前
设计模式-创建型-抽象工厂模式
设计模式·抽象工厂模式
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
小白不太白9503 小时前
设计模式之 观察者模式
观察者模式·设计模式
小白不太白9504 小时前
设计模式之 责任链模式
python·设计模式·责任链模式
吾与谁归in4 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in4 小时前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
闲人一枚(学习中)5 小时前
设计模式-创建型-原型模式
设计模式
Iced_Sheep5 小时前
干掉 if else 之策略模式
后端·设计模式
哪 吒12 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_102212 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee