访问者模式在《Design Patterns: Elements of Reusable Object-Oriented Software》的定义如下:
Represent an operation to be performed on the elements of an object structure.Visitor lets you define a new operation without changing the classes of the elements on which it operates.
对于访问者模式的优缺点或者代码样例可以参考电子工业出版社的《Java 与模式》和清华大学出版社的《Java设计模式》
下面将重点介绍在函数式编程中如何实现访问者模式
在不改变原有类的情况下增加新的操作,这里用到了scala中的隐式类,指的是用implicit关键字修饰的类。
- 下面的样例中,在不改变SimplePerson类的前提下,想增加一个操作fullAddress,只要增加一个
implicit class ExtendedPerson
类,那么就可以直接调用simplePerson.fullAddress
,这里操作的是SimplePerson中的houseNum和street属性 - 虽然ComplexPerson 和SimplePerson 实现方式不同,但是
implicit class ExtendedPerson
同样适用
object VisitorPattern {
trait Person {
def fullName: String
def firstName: String
def lastName: String
def houseNum: Int
def street: String
}
class SimplePerson(val firstName: String, val lastName: String,
val houseNum: Int, val street: String) extends Person {
def fullName = firstName + " " + lastName
}
implicit class ExtendedPerson(person: Person) {
def fullAddress = person.houseNum + " " + person.street
}
class ComplexPerson(name: Name, address: Address) extends Person {
def fullName = name.firstName + " " + name.lastName
def firstName = name.firstName
def lastName = name.lastName
def houseNum = address.houseNum
def street = address.street
}
class Address(val houseNum: Int, val street: String)
class Name(val firstName: String, val lastName: String)
def main(args: Array[String]): Unit = {
val simplePerson = new SimplePerson("Mike", "Linn", 123, "Fake. St.")
println(simplePerson.fullName)
println(simplePerson.fullAddress)
val name = new Name("Tom", "Linn")
val address = new Address(456, "Fake St.")
val complexPerson = new ComplexPerson(name, address)
println(complexPerson.fullName)
println(complexPerson.fullAddress)
}
}
输出结果为
Mike Linn
123 Fake. St.
Tom Linn
456 Fake St.