python实现访问者模式

先看这个简单的例子:

http://dongweiming.github.io/python-visitor.html

 然后看这个例子:

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

class NodeVisitor:
    def visit(self, node):
        methname = 'visit_' + type(node).__name__
        meth = getattr(self, methname, None)
        if meth is None:
            meth = self.generic_visit
        return meth(node)

    def generic_visit(self, node):
        raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))

class Evaluator(NodeVisitor):
    def visit_Number(self, node):
        return node.value

    def visit_Add(self, node):
        return self.visit(node.left) + self.visit(node.right)

    def visit_Sub(self, node):
        return self.visit(node.left) - self.visit(node.right)

    def visit_Mul(self, node):
        return self.visit(node.left) * self.visit(node.right)

    def visit_Div(self, node):
        return self.visit(node.left) / self.visit(node.right)

    def visit_Negate(self, node):
        return -node.operand

t1 = Sub(Number(3), Number(4))
t2 = Mul(Number(2), t1)
t3 = Div(t2, Number(5))
t4 = Add(Number(1), t3)
e = Evaluator()
print(e.visit(t4))

结果是

0.6

 

上面也使用了访问者模式。Evaluator是访问者,每次改变改变这里。

 1 class Node:
 2     pass
 3 
 4 class UnaryOperator(Node):
 5     def __init__(self, operand):
 6         self.operand = operand
 7 
 8 class BinaryOperator(Node):
 9     def __init__(self, left, right):
10         self.left = left
11         self.right = right
12 
13 class Add(BinaryOperator):
14     pass
15 
16 class Sub(BinaryOperator):
17     pass
18 
19 class Mul(BinaryOperator):
20     pass
21 
22 class Div(BinaryOperator):
23     pass
24 
25 class Negate(UnaryOperator):
26     pass
27 
28 class Number(Node):
29     def __init__(self, value):
30         self.value = value
31 
32 class NodeVisitor:
33     def visit(self, node):
34         methname = 'visit_' + type(node).__name__
35         meth = getattr(self, methname, None)
36         if meth is None:
37             meth = self.generic_visit
38         return meth(node)
39 
40     def generic_visit(self, node):
41         raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))
42 
43 class StackCode(NodeVisitor):
44     def generate_code(self, node):
45         self.instructions = []
46         self.visit(node)
47         return self.instructions
48 
49     def visit_Number(self, node):
50         self.instructions.append(('PUSH', node.value))
51 
52     def binop(self, node, instruction):
53         self.visit(node.left)
54         self.visit(node.right)
55         self.instructions.append((instruction,))
56 
57     def visit_Add(self, node):
58         self.binop(node, 'ADD')
59 
60     def visit_Sub(self, node):
61         self.binop(node, 'SUB')
62 
63     def visit_Mul(self, node):
64         self.binop(node, 'MUL')
65 
66     def visit_Div(self, node):
67         self.binop(node, 'DIV')
68 
69     def unaryop(self, node, instruction):
70         self.visit(node.operand)
71         self.instructions.append((instruction,))
72 
73     def visit_Negate(self, node):
74         self.unaryop(node, 'NEG')
75 
76 t1 = Sub(Number(3), Number(4))
77 t2 = Mul(Number(2), t1)
78 t3 = Div(t2, Number(5))
79 t4 = Add(Number(1), t3)
80 e = StackCode()
81 print(e.generate_code(t4))

结果是

[('PUSH', 1), ('PUSH', 2), ('PUSH', 3), ('PUSH', 4), ('SUB',), ('MUL',), ('PUSH', 5), ('DIV',), ('ADD',)]

 

posted on 2017-02-07 15:59  wzxds02  阅读(384)  评论(0编辑  收藏  举报

导航