Scala patterns (#1) - Option
自从1994年《设计模式:可复用面向对象软件的基础》问世以来,设计模式就备受关注,虽然业界褒贬不一,而且有人专门写了反模式来陈述其弊端,但大家对它的作用大部分还是认可的,尤其是在面向对象编程领域。但是,正如Brooks所说的“天下没有免费的银弹”,软件的本质问题是管理复杂度,所以能用设计模式解决问题,它必然也会带来衍生问题,工具都有利弊,如何更好地使用工具才是王道。为了减少对设计模式的滥用和简化设计(既然可复用,为什么不直接让语言天生支持呢?),多年以来,人们一直期望在语言层面增加对可复用编程模式(pattern/paradigm)的支持,而这些想法确实也逐渐被多种现代编程语言所采纳。
在学习Scala语言的过程中,我感觉程序员得到了以往学习任何语言都不曾有过的待遇:在语言层面对于模式的支持已经达到了相当丰富的程度。当然,受限于现在所学的知识,还不能把Scala中的设计模式尽数解读,但是我准备用一个系列把Scala中涉及的设计模式写出来,这样做的好处之一是能从应用层面能更好地使用这些模式(准确地说,是语言元素或语法),之二是能更深入地理解设计模式本身。当然,如果没有伟大的互联网,有些工作是很难开展的,本文内容大部分都是基于网络资源和前辈的工作完成的。
Option模式
Scala in action中提到了几种模式,今天我们先聊聊Option模式,不过这种模式不是《设计模式》书中定义的一种,是编外的一种模式(参考Null对象模式),作者在书中给出了来源,可能是较早讨论Option模式的一篇博文。这篇文章有点长,我简单解释一下,博主基本上分三点(Option在Scala中的应用、Option和null的比较以及Java中Option的手工实现)讨论Option,我们重点关注第一点,那就是使用一个除法函数来说明Scala内嵌Option的用法,如下所示:
|
|
这个函数还算比较直观,只是里面用到了Currying(柯里化,或参见博主另一篇文章)和递归,我们可以暂时忽略这些,只关注返回值。返回值在这里定义为Option[Int],在函数中返回的结果可能是None、Some(0)或者Some(其他值),很容易理解吧?
作者继续讨论了使用Option两种方式的异同:第一种就是上述除法函数的例子,这并不是一种很好的方法(思考一下为什么),而第二种则是使用模式匹配,则会更优雅一些:
|
|
为什么null是糟糕的?
如果你写过Java程序可能会比较有感触,100行程序至少得有10行以上得和null的处理逻辑相关吧?这篇博文也对Option和null的使用方式做了个比较,但我更喜欢SlideShare上的一个屁屁踢Option, Either, Try中的例子,摘抄如下:
Java中使用null的例子
|
|
为什么null容易出错(注释译成了中文)
|
|
看完这个例子,已经不需要解释了。强烈建议喜欢Scala的同学看完这个Slides,有内涵。
Option模式是怎么定义的
Option在Scala中的定义只是这样的:
|
|
这里Option是一个抽象类,有两个case class实现,一个是Some,代表有值,另一个是None,代表空值,也就是“具有一个或零个元素的容器”。其中+A是Scala中协变(简单理解就是对类型A以及其子类型适用)的意思,请参考相关文档。
总体来说,借用Michal Bigos的Slides,Option模式的好处有以下几点:
- 在类型层面规定值存在或不存在
- 编译器强迫程序员处理Option
- 不会意外地依赖不存在的值
- 清晰地描述了设计意图
所以,学习一下Option,在你的程序里用起来吧!
参考资源
- Scala语言中的设计模式
- 关于“Option”模式
- Option, Either, Try and what to do with corner cases when they arise
- Design Patterns in Scala
说明:文中任何引用部分版权均归原文作者所有,引用请注明本文地址和原文地址。文中任何拼写或摘抄错误均由本文作者负责纠正。