Scala设计模式Part II. 结构化模式———2.桥接模式

意图

从实现中分离抽象,使得两者都可以独立变化。

桥接模式可以避免抽象与其实现之间的永久绑定。桥接模式对于一系列可扩展类非常重要,一般来说从一个类层次定义若干核心抽象,通过继承具体实现,每个都需要不同的实现。典型的例子是UI框架的窗口抽象。核心抽是窗口,它被子类具体实现。然后每个子类又被不同平台相应的窗口子类继承,这导致了子类的增生。这创建了抽象和实现之间永久的绑定,使得系统硬性绑定在一起。抽象的改变会导致所有子类的改变。解决方法是把类层次分解成为两个独立的层次,一个用于抽象另外一个用于实现。这减少了系统中类的数量,使得每个层次互相独立。下图展示了两个层次直接的关系。

这里写图片描述

Abstraction中所有的操作被Implementor中的抽象方法具体实现。这是两者解耦的关键。

分析

桥接模式本身通过组合和委托实现。抽象包含了指向实现的引用。实现的具体类型通过抽象类隐藏,这种组合实现了解耦,符合了GOF的第二准则(对象组合优于类继承)。

使用组合、委托替代类继承的重构方式,可以使用Scala的self type。这样做的代价是无法在运行时改变绑定。

组件化

在讲适配器模式时,我们讲过无法以一种有意义的方式抽象类之间的通信。抽象和实现层次之间的通信在不同的模式实例中差别巨大。不同实例之间唯一保持相同的是概念层次上的相关角色,这意味着没有可组件化的内容。

Scala方案

在下面代码中,根抽象是Window,它有一个指向根实现的self type叫做WindowImp。

trait Window {
  self:WindowImp=>
  def drawRect(x1:Int,x2:Int,x3:Int,x4:Int) = {
    drawLine(x1,x2)
    drawLine(x1,x3)
    drawLine(x2,x4)
    drawLine(x3,x4)
  }
}

//抽象
trait TransientWindow {
  self:Window=>
  def drawCloseBox = drawRect(4,3,2,1)
}

trait IconWindow {
  self:Window=>
  def drawBorder = drawRect(1,2,3,4)
}

//所有实现的通用接口
trait WindowImp {
  def drawLine(x:Int,y:Int)
}

//实现
trait WindowOSX extends WindowImp {
 def drawLine(x:Int,y:Int)=println("drawing line in OSX")
}

trait WindowVista entends WindowImp {
  def drawLine(x:Int,y:Int)=println("drawing line in Vista")
}

def main(args:Array[String])={
  val windowOSX:Window = new Window with WindowOSX
  windowOSX.drawRect(1,2,3,4)
}

-----
drawing l ine in OSX
drawing l ine in OSX
drawing l ine in OSX
drawing l ine in OSX

我们需要在Window的子类中重复声明自身类型。另外一种较为繁琐的使用自身类型的方式是将定义所需的操作定义为抽象成员。这样更加灵活,因为无需命名具体的特质。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值