8.21 实现访问者模式
问题
你要处理由大量不同类型的对象组成的复杂数据结构,每一个对象都需要需要进行不同的处理。 比如,遍历一个树形结构,然后根据每个节点的相应状态执行不同的操作。
解决方案
假设你要写一个表示数学表达式的程序,那么你可能需要定义如下的类:
class Node:
pass
class UnaryOperator(Node):
def __init__(self, operand):
self.operand = operand
class BinaryOperator(Node):
def __init__(self, left, right):
self.left = left
self.right = right
class Add(BinaryOperator):
pass
class Sub(BinaryOperator):
pass
class Mul(BinaryOperator):
pass
class Div(BinaryOperator):
pass
class Negate(UnaryOperator):
pass
class Number(Node):
def __init__(self, value):
self.value = value然后利用这些类构建嵌套数据结构,如下所示:
这样做的问题是对于每个表达式,每次都要重新定义一遍,有没有一种更通用的方式让它支持所有的数字和操作符呢。 这里我们使用访问者模式可以达到这样的目的:
为了使用这个类,可以定义一个类继承它并且实现各种 visit_Name() 方法,其中Name是node类型。 例如,如果你想求表达式的值,可以这样写:
使用示例:
作为一个不同的例子,下面定义一个类在一个栈上面将一个表达式转换成多个操作序列:
使用示例:
讨论
这里访问者模式的好处就是通过 getattr() 来获取相应的方法,并利用递归来遍历所有的节点:
这种技术也是实现其他语言中switch或case语句的方式。 比如,如果你正在写一个HTTP框架,你可能会写这样一个请求分发的控制器:
访问者模式一个缺点就是它严重依赖递归,如果数据结构嵌套层次太深可能会有问题, 有时候会超过Python的递归深度限制(参考 sys.getrecursionlimit() )。
在跟解析和编译相关的编程中使用访问者模式是非常常见的。 Python本身的 ast 模块值的关注下,可以去看看源码。
Last updated
Was this helpful?