学习Scala的定义工厂对象
创始人
2024-04-19 04:21:31
0

你现在有了布局元素的类层级。这个层级可以“依原件”展现给你的客户。但是你或许还是选择把层级隐藏在工厂对象之后。工厂对象包含了构建其它对象的方法。客户与实惠使用这些工厂方法实现对象的构造而不是直接使用new构造对象。这种方式的一个好处是对象的创建可以被集中化并且对象实际代表类的细节可以被隐藏。这种隐藏一方面简化客户理解你的库,因为更少的细节被暴露出来,另一方面提供给你更多机会在之后改变库的实现而不会破坏客户代码。

51CTO编辑推荐:Scala编程语言专题

为布局元素构建工厂的第一任务是选择工厂方法应该放在哪儿。它们应该是单例对象成员还是类成员?包含它们的对象或类应该怎么调用?这里有许多可能性。最直接的方案是创建类Element的伴生对象并把它做成布局元素的工厂方法。对于这种方式,你唯一要暴露给客户的就是Element的类/对象组合,隐藏它的三个实现类ArrayElement,LineElement和UniformElement。

代码10.10是遵循了这个方案的设计。Element伴生对象包含了三个重载的elem方法变体。每一个变体构建一种不同的布局对象。

  1. object Element {  
  2. def elem(contents: Array[String]): Element =  
  3. new ArrayElement(contents)  
  4. def elem(chr: Char, width: Int, height: Int): Element =  
  5. new UniformElement(chr, width, height)  
  6. def elem(line: String): Element =  
  7. new LineElement(line)  
  8. }  
代码 10.10 带有工厂方法的工厂对象

这些工厂方法使得改变类Element的实现通过使用elem工厂方法实现而不用显式地创建新的ArrayElement实例成为可能。为了不使用单例对象的名称,Element,认证而调用工厂方法,我们将在源文件顶上引用Element.elem。换句话说,代之以在Element类内部使用Element.elem调用工厂方法,我们将引用Element.elem,这样我们只要使用它们的简化名,elem,就可以调用工厂方法。代码10.11展示了类Element在这些改变之后的样子。

  1. import Element.elem  
  2. abstract class Element {  
  3. def contents: Array[String]  
  4. def width: Int =  
  5. if (height == 0) 0 else contents(0).length  
  6. def height: Int = contents.length  
  7. def above(that: Element): Element =  
  8. elem(this.contents ++ that.contents)  
  9. def beside(that: Element): Element =  
  10. elem(  
  11. for (  
  12. (line1, line2) < - this.contents zip that.contents  
  13. ) yield line1 + line2  
  14. )  
  15. override def toString = contents mkString "\n" 
  16. }  
代码 10.11 重构以使用工厂方法的类Element

而且,有了工厂方法之后,子类ArrayElement,LineElement和UniformElement现在可以是私有的,因为它们不再需要直接被客户访问。Scala里,你可以在类和单例对象中定义其它的类和单例对象。因此一种让Element的子类私有化的方式就是把它们放在Element单例对象中并在那里声明它们为私有。需要的时候,这些类将仍然能被三个elem工厂方法访问。代码10.12展示了其中的细节。

  1. object Element {  
  2.  private class ArrayElement(  
  3.   val contents: Array[String]  
  4.  ) extends Element  
  5.  private class LineElement(s: String) extends Element {  
  6.   val contents = Array(s)  
  7.   override def width = s.length  
  8.   override def height = 1 
  9.  }  
  10.  private class UniformElement(  
  11.   ch: Char,  
  12.   override val width: Int,  
  13.   override val height: Int  
  14.  ) extends Element {  
  15.   private val line = ch.toString * width  
  16.   def contents = Array.make(height, line)  
  17.  }  
  18.  def elem(contents: Array[String]): Element =  
  19.   new ArrayElement(contents)  
  20.  def elem(chr: Char, width: Int, height: Int): Element =  
  21.   new UniformElement(chr, width, height)  
  22.  def elem(line: String): Element =  
  23.   new LineElement(line)  
  24. }  

代码 10.12 用私有类隐藏实现

【相关阅读】

  1. 如何实现Scala的above,beside和toString
  2. Scala学习:使用组合与继承
  3. 在Scala中定义final成员
  4. Scala程序中如何实现多态和动态绑定
  5. Scala学习:调用超类构造器和override修饰符的使用

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...