设计模式 – Scala中的访客模式
有没有任何用例在Scala中使用
Visitor Pattern?
每次在Java中使用访客模式时,我应该在Scala中使用Pattern Matching吗? 解决方法
是的,您应该可以从模式匹配开始,而不是访问者模式。看这个
interview with Martin Odersky(我的重点):
编辑:我认为这需要一个更好的解释和一个例子。访问者模式通常用于访问树或类似的每个节点,例如抽象语法树(AST)。使用优秀的Scalariform.的例子Scalariform格式scala代码通过解析Scala,然后遍历AST,写出来。提供的方法之一采用AST,并按顺序创建所有令牌的简单列表。用于此的方法是: private def immediateAstNodes(n: Any): List[AstNode] = n match { case a: AstNode ? List(a) case t: Token ? Nil case Some(x) ? immediateAstNodes(x) case xs @ (_ :: _) ? xs flatMap { immediateAstNodes(_) } case Left(x) ? immediateAstNodes(x) case Right(x) ? immediateAstNodes(x) case (l,r) ? immediateAstNodes(l) ++ immediateAstNodes(r) case (x,y,z) ? immediateAstNodes(x) ++ immediateAstNodes(y) ++ immediateAstNodes(z) case true | false | Nil | None ? Nil } def immediateChildren: List[AstNode] = productIterator.toList flatten immediateAstNodes 这是一个可以通过Java中的访问者模式完成的工作,但通过Scala中的模式匹配更简洁地完成。在Scalastyle(Scala的Checkstyle)中,我们使用这种方法的修改形式,但是有一个微妙的变化。我们需要遍历树,但每个检查只关心某些节点。例如,对于EqualsHashCodeChecker,它只关心定义的equals和hashCode方法。我们使用以下方法: protected[scalariform] def visit[T](ast: Any,visitfn: (Any) => List[T]): List[T] = ast match { case a: AstNode => visitfn(a.immediateChildren) case t: Token => List() case Some(x) => visitfn(x) case xs @ (_ :: _) => xs flatMap { visitfn(_) } case Left(x) => visitfn(x) case Right(x) => visitfn(x) case (l,r) => visitfn(l) ::: visitfn(r) case (x,z) => visitfn(x) ::: visitfn(y) ::: visitfn(z) case true | false | Nil | None => List() } 请注意,我们递归调用visitfn(),而不是visit()。这允许我们重复使用这种方法遍历树而不重复代码。在我们的EqualsHashCodeChecker中,我们有: private def localvisit(ast: Any): ListType = ast match { case t: TmplDef => List(TmplClazz(Some(t.name.getText),Some(t.name.startIndex),localvisit(t.templateBodyOption))) case t: FunDefOrDcl => List(FunDefOrDclClazz(method(t),Some(t.nameToken.startIndex),localvisit(t.localDef))) case t: Any => visit(t,localvisit) } 所以这里唯一的样板是模式匹配的最后一行。在Java中,上述代码可以很好地被实现为访问者模式,但是在Scala中,使用模式匹配是有意义的。还要注意,除了定义unapply()之外,上述代码不需要对正在遍历的数据结构进行修改,如果您正在使用案例类,则会自动执行。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |