Java设计模式之Adapter模式

一、概述:

提到Adapter适配器相信很多人都特别熟悉了,在我们开发中经常出现一些实现继承适配器去完成某项功能,使用最多的可能就是ListView和RecyclerView的是适配器了,不知道有没有同学想过适配器的作用呢?为什么要使用这些适配器?以及他们所带来的好处呢?

下面我们举个例子:如果你去了某个地方,准备要给你的手机充电,发现整个房间的都是三孔插座,而你的手机充电器只能使用两空,这时你会去前台寻求帮助,前台可能会给你一个带有两空的插板,这时你回去把插板插在房间的三孔插座你的手机就可以充电了,我们来分析下这个过程,:

  • 需求:两孔充电插座
  • 条件:三孔电源插座
  • 解决方法:插线板

上述过程使用了插线板将三孔插座抓还为两孔充电,插线板起到了将三孔插座电源适配给两孔充电器的功能,也就是Adapter的功能。在程序中将这种用于填补“现有程序”和“所需程序”之间差异的设计模式叫Adapter(适配器)模式。

Adapter模式分为两种:

  • 类适配器:需要继承类来实现
  • 对象适配器:需要委托对象实现

下面我们分别来介绍若何实现这两个适配器:

二、类适配器

假设现在需要12伏的电压,可是只提供100V的电压输出,需要采用适配器来转换为12V,我们按照上面的例子分析这个问题:

  • 需求:12V电压
  • 条件:100V电压
  • 适配器:100V转换为12V

现在我们将上述需求和条件转换为想用的代码实现:

需求接口获得12V的电压:

interface ElegantTwenty {

    fun getElegantT(): Int
}

创建ElegantHundreds类,提供100V电压:

open class ElegantHundreds {

    private val elegant: Int = 10
    fun getEle(): Int {
        return elegant * 10
    }
}

为了能将提供的100V电压转化为所需的12V,我们提供一个电压适配器ElegantAdapter用于电压转换,为了能获取提供的电压,我们让ElegantAdapter继承ElegantHundreds,并实现需求的接口,提供需求方法,这里做一个简单的处理将电压降低88V:

class ElegantAdapter : ElegantHundreds(),ElegantTwenty {
    
    override fun getElegantT(): Int {
        var ele = getEle()
        return ele - 88
    }
}

现在我们去获取电压,看看能不能获取到所需的12V电压:

var elegantTwenty: ElegantTwenty = ElegantAdapter()
        var elegant = elegantTwenty.getElegantT()
        tvElegant.text = "ElegantAdapter 获取的电压为 ${elegant}V"

输出的电压为:

Java设计模式之Adapter模式_第1张图片

此时已经使用适配器将电压转换为12V了,相信适配器的作用大家都了解了,就是创建一个具体类继承原有功能并实现需求接口,从而达到两者转换的目的,但可能会有同学说如果需求不是接口呢?那根据Java的单继承关系就不能实现上面的关系了,那该怎么办呢?这种情况就是上面所说的第二种委托式的适配器。

三、对象适配器

现在我们将上面的需求接口ElegantTwenty改成类:

abstract class ElegantTwenty {
   abstract fun getElegant12():Int
}

在适配继承需求类ElegantTwenty后,就无法继承ElegantHundreds,所以可以在适配器中创建ElegantHundreds的对象,将所有的相关操作委托给创建的对象操作:

class Adapter : ElegantTwenty(){
//创建一个ElegantHundreds的对象作为委托对象
   private val elegant by lazy {
        ElegantHundreds()
    }
    override fun getElegant12(): Int {
     return  elegant.getEle() - 88
    }
}

现在去获取12V电压的方法中会先委托对象拿去提供的100V电压,然后转化为12V,现在我们去获取电压:

var elegant12 : ElegantTwenty = Adapter()
        var v = elegant12.getElegant12()
        textView.text = "ElegantAdapter 获取的电压为 ${v}V"


四、登场角色

到这两种适配器的使用方式都介绍完了,这里只是用简单的实例演示具体的使用方法,下面我们来看看Adapter的登场角色

  • Target:定义需求方法(如:ElegantTwenty)
  • Client:具体的请求者(如:MainActivity等使用的地方)
  • Adaptee:被适配的角色,通常为一个持有既定方法的角色(如:ElegantHundreds)
  • Adapter:适配器,对Adaptee角色和Target之间的转换(如:ElegantAdapter)

在类适配其中,Adapter通过继承Adaptee,而在对象适配其中Adapter中持有Adaptee对象,通过对象委托实现。

五、使用场景

既然学会了Adapter的使用,那我们在什么情况下选择使用Adapter模式呢?

  • 扩展代码适应性。对已有的经过测试封装好的代码,这样的代码往往不要轻易的修改,但为了适用于不同的项目和条件,这时就要使用适配器进行适配处理
  • 避免更多的修改。当我们写好一个需求后当需求发生一点改变时,很多同学会认为我修改一个某段的代码就可以,可是修改后发现牵一发而动全身,这时就可以使用Adapter模式避免修改问题的发生
  • 版本升级和兼容。假设在版本不断升级时某一个地方的功能有了新的实现,可是要适配之前的版本,为了避免每次都要同时修改心就版本,可以采用适配模式让旧版本适配新程序,以后只要对新程序的维护。
  • 联系功能完全不同的两个类。通过适配器让两者联系起来实现某种需求。

今天适配模式的介绍就到这里了,周末结束了,又是新的一周继续努力!

你可能感兴趣的:(Java设计模式之Adapter模式)