Scala设计模式Part I. 创建模式——1.抽象工厂

来源:互联网 发布:数据库实例是什么 编辑:程序博客网 时间:2024/06/14 00:12

描述

抽象工厂的目的是为创建一系列相关或者依赖的对象提供一个接口,而不用指定具体的类

例如我们要开发一个可以兼容不同OS平台GUI库,为了能够为图形窗口提供统一的视觉感受,在维护能跨OS运行的代码时,只能暴露window的接口给使用户用。通常窗口由多个挂件(菜单,按钮)组成,其中有些挂件与平台绑定。事实上不同平台上窗口的具体创建代码通过抽象工厂进行了分离。这样可以使我们有足够的灵活性来修改不同平台上的创建代码,而不必修改使用抽象工厂的用户代码,因为客户程序并不知道具体实现类的存在,也不会再客户程序中引入平台依赖。只要依赖于抽象接口,看起来我们改变了窗体及相关挂件的实现,并且提供了新的版本,但是实际上并没有改变客户端代码。工厂通常都会创建一系列的产品,在我们的GUI库的例子中这些产品可能是window、menubar。一个值得我们注意的问题是,我们不能混合使用依赖于不同平台的类,因为这会导致运行时的错误。
具体的工厂通常会被实现为单例模式。

分析

在最初的解决方案中没有保证禁止不同工厂创建的产品混合使用。这会在产品互相依赖的时候出现问题,例如A CreateProductA(B)。只有在使用工厂时注明这一禁止要求才可以避免混合使用。可以通过抽象类型成员表示产品的互相依赖,从理论上来讲这可以为复用工厂的子类创造更多的机会。

这里写图片描述

可以把从特定工厂创建的所有产品看做是一个产品家族,很显然这个模式可以从Scala版本的家族多态(family polymorphism)中获得相应的支持。
可以通过嵌套的类以及访问控制来封装具体类型。创建代码被封装在工厂类里面。

模块化

每个工厂实例有以下几处不同(可以被抽象):
- 产品类型
- 产品数量
- 创建代码
产品的类型可以由Scala的抽象类型成员进行抽象。创建代码的抽象可以由传入工厂方法的一等函数表达。但遗憾的是不能很好地抽象产品数量。这可以通过提供多个抽象工厂类解决,这多个工厂类唯一的不同就是产品数量的差异。
通过上面所述的解决方案,我们失去了表示产品之间互相依赖的能力,同时失去了将具体类型以嵌套的方式干净利落的封装的能力。下面的例子展示了一个可创建两个产品的可重用工厂。

abstract class Factory {  type T1  type T2  def createA(f:()=>T1)  def createB(f:()=>T2)}

Scala的解决方案

trait WindowFactory {  type aWindow <: Window  type aScrollbar <: Scrollbar  def createWindow(s:aScrollbar)  def createScrollbar()  abstract class Window(s:aScrollbar)  abstract class Scrollbar}object VistaFactory extends WindowFactory {  type aWindow=VistaWindow  type aScrollbar=VistaScrollbar  def createWindow(s:aScrollbar)=new VistaWindow(s)  def createScrollbar()=new VistaScrollbar  protected class VistaWindow(s:aScrollbar) extends Window(s)  protected class VistaScrollbar extends Scrollbar}

为了对产品类模块进行更好的维护,在工厂类内部实现产品类并不是最佳方案。建议使用隐含的自身类型(self type)来表示任何提供产品类的模块与WindowFactory之间的依赖。这样可以在工厂类作用域以外的地方扩展Window和Scrollbar。

trait VistaWidgets {self: WindowFactory=>protected class VistaWindow(s:aScrollbar) extends Window(s)protected class VistaScrollbar extends Scrollbar

小结

嵌套类可以用户封装特定类型。工厂从本质上来看只是一个为特定类型提供的带独立命名空间的特质(trait)。抽象类型可以表示产品间的互相依赖。通过这种方式可以以一种静态的方式保证不同工厂创建的产品不能够互相混用(比如family polymorphism)。除此以外,这也增加了复用工厂子类的机会。

超越GOF设计模式的特性
1. 产品互相依赖性:原有设计无法混用不同工厂生产的产品。
2. 单例工厂并不是实现重点。
3. 嵌套产品类:可以很容易的对客户隐藏实现类。

0 0
原创粉丝点击