2012-03-22 43 views
10

据我所知,访客模式通常用于将方法添加到某些层次结构中。但我还是不明白:看到我尽量突出左子树的例子:如何在JavaScript中实现访客模式?

subtree highlighting

的Javascript树的实现:

function node(val) { 
    this.value = val; 
    this.left = this.right = null; 
    } 

    var tree = new node("A"); 
    tree.left = new node("B1"); 
    tree.right = new node("B2"); 
    tree.left.left = new node("C1"); 
    tree.left.right = new node("C2"); 

我想我使用访客模式的高亮:

node.prototype.accept = function(visitorObj) { 
    visitorObj.visit(this); 
} 

function visitor() { 
    var that = this; 
    this.visit = function(tgt) { 
    tgt.value = "*"+tgt.value; 
    } 
    this.highlight = function(tgt) { 
    tgt.accept(that); 
    if(tgt.left) that.highlight(tgt.left); 
    if(tgt.right) that.highlight(tgt.right); 
    } 
} 

(new visitor()).highlight(tree.left); 

但为什么要使用接受访方法,当它可以更简单?

function visitor() { 
    var that = this; 
    this.highlight = function(tgt) { 
    tgt.value = "*"+tgt.value; 
    if(tgt.left) that.highlight(tgt.left); 
    if(tgt.right) that.highlight(tgt.right); 
    } 
} 

(new visitor()).highlight(tree.left); 

它与this example类似。这是否意味着如果语言混合类型(如javascript),没有理由接受访问对呢?

回答

15

你在执行过程中遗漏了一些东西。假设Node元素的左侧和右侧属性是私有的。那么你如何在你的实施中强调它们?

访问者不应该意识到树结构,并让节点元素在任何子元素上运行访问者,这是直接子元素。所以,你的代码应该是这样的:

node.prototype.accept = function(visitorObj) { 
    visitorObj.visit(this); 
    if (this.left) this.left.accept(visitorObj); 
    if (this.right) this.right.accept(visitorObj); 
} 

function visitor() { 
    var that = this; 
    this.visit = function(tgt) { 
     tgt.value = "*"+tgt.value; 
    } 
    this.highlight = function(tgt) { 
     tgt.accept(that); 
    } 
} 

(new visitor()).highlight(tree.left); 

这样访问者没有树的知识结构,它是通用的,具有属性“价值”的任何节点上会工作。

+1

在J.Bishops的书中,我被这个错误蒙上了一层阴影。我花了数小时沉思,现在它非常清晰 - 非常感谢! – 2012-03-22 23:25:51

+0

这是一个相当古老的凹凸,但我很努力地找出写在那里的差异,并且这是: ''' node.prototype.accept = function(visitor){ visitor(this); this.left && this.left.accept(visitor); this.right && this.right.accept(visitor); } ''' 主要区别在于,不是使用访问方法传递对象,而是传递函数。看起来您看到的访问者模式示例似乎是没有一流功能的语言,只是使用对象来传输方法。 你的答案能做什么,我的不能,如果有的话? – Tom 2014-03-31 17:37:56

+1

@Tom如果需要的话,你的函数将在哪里整理值?由于它的功能它不会有一个有效的“本”(http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work)。通过使用一个对象,你可以存储任何你想要的东西。 – Bae 2015-11-11 06:37:11