Scala设计模式Part II. 结构化模式———1.适配器

描述

适配器模式的意图是:

把一个类的接口转换成客户端期望的另一个接口。适配器可以让彼此不兼容的接口协同工作。

GOF给出了两种基本的适配器实现:类适配器和对象适配器。他们各有优缺点。

类适配器使用继承实现一个类到另一个类的适配。如下图所示适配器类继成了Adaptee和适配目标Target接口。客户端在适配目标类上调用具体的操作时,适配器类会从被适配的类中调用相应的继承方法。继承可以通过重载方法补充被适配类的行为,但是这样适配器类建立了与被适配类之间静态的依赖关系。这意味着适配器类不能被被适配类的子类重用。

这里写图片描述

对象适配器使用组合/代理而非继承作为适配实现的主要机制。如下图所示,Adapter类包含了一个指向被适配类的引用。客户端调用Request方法时,消息被传递给被适配类的对象。因为适配器只包含了一个指向被适配类的引用,所有它没有与其他类之间的静态依赖,适配器类可以被被适配类的子类重用。但代价是引入了自身问题(self problem),并且不能重载被适配类的行为。

这里写图片描述

两种适配器方式对客户端是透明的,客户端只使用目标接口处理他们想要适配的被适配接口。

分析

考虑对象适配器,上述第二种适配器方式更有效。
明确的自类型(self type)能消除继承适配器带来的适配器和具体被适配类之间依赖的问题。一种更加灵活的方式是用抽象成员声明所需的方法而非自类型。组合混入可以构建一个双重适配器,因为构建的复合类型可对目标类和被适配类都实现适配器功能。另外,这也消除了自身问题。

综合上述特性增强了GOF的两种模式方案,但是不能再运行时改变被适配的类,在某些场景下这是很重要的。

组件化

每次实例化不同的地方是适配器、被适配类的类型以及他们之间的通信。通信一般通过所涉一系列方法实现。在Scala中没有方式实现对一系列类成员的抽象,这意味着我们不能提供可用的组件。

适配器可被被适配类的任何子类复用,但是这也是有模式适用的特定上下文背景。

Scala解决方案

Scala方案结合了类适配器和对象适配器的优点,同时也有双重适配器的功能。下面代码是一个简单的例子。模式的关键是Adapter特质。它定义了明确的自类型——复合类型Target with Adapter,消除了适配器对被适配类的依赖。

trait Target {
  def Request 
}

class Adaptee {
  def SpecificRequest = println("Specific Request!")
}

trait Adapter {
  self : Target with Adaptee=>
  def Request()=self.SpecificRequest()
}

def main(args:Array[String])= {
  val adapter=new Adaptee with Target with Adapter
  adapter.Request
  adapter.SpecificRequest
}

main方法展示了如何使用适配器。它可以调用Request和SpecificRequest方法,证明其可以处理双重适配器。

总结

Scala方案结合了类适配器和对象适配器所有的优点,消除了自身问题。自类型的使用消除了对特定被适配类的依赖。另一种方案是在适配器类中声明抽象成员,这样能增加灵活性,因为只引入了结构上的依赖。这种方案仅有部分基于组合的灵活性,同时也说明在应用于Scala时没有第一种强大。因为无法抽象类的成员集合,所以无法组件化。

与GOF方案相比,Scala方案有如下特点:

  • 没有self problem,但是几乎与对象适配器一样灵活
  • 与类适配器相比,没有对特定被适配类的依赖
  • 只适用于不需要动态改变被适配类的情况
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值