【问题标题】:How to implement visitor pattern in javascript?如何在javascript中实现访问者模式?
【发布时间】:2012-03-22 22:20:43
【问题描述】:

据我了解,访问者模式通常用于向某些层次结构添加方法。但我仍然不明白:请参阅我尝试突出显示左子树的示例:

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);

但是为什么要使用 accept-visit 方法,因为它可以更直接?

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),则根本没有接受访问对的理由?

【问题讨论】:

    标签: javascript design-patterns visitor-pattern


    【解决方案1】:

    您在实施过程中遗漏了一些东西。想象一下 Node 元素的 left 和 right 属性是私有的。那么你将如何在你的实现中突出它们呢?

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

    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);
    

    这种方式访问​​者不知道树的结构,它是通用的,可以在任何具有“值”属性的节点上工作。

    【讨论】:

    • 我被 J.Bishops 书中的这个错误蒙蔽了双眼。我花了几个小时思考它,现在很清楚 - 非常感谢!
    • 这是一个相当古老的凹凸,但我正在努力找出那里写的内容与以下内容之间的区别:``` node.prototype.accept = function (visitor) { visitor(这); this.left && this.left.accept(visitor); this.right && this.right.accept(访客); } ``` 主要区别在于,不是通过访问方法传递对象,而是只传递一个函数。您看到的访问者模式示例似乎是针对没有一流函数的语言,并且只是使用对象来传输方法。如果有的话,你的答案能做什么我不能做的?
    • @Tom 如果需要,您的函数将在哪里整理值?由于它是一个函数,它不会有一个有效的“this”(stackoverflow.com/questions/3127429/…)。通过使用一个对象,你可以在其中存储任何你想要的东西。
    • @Bae。该函数可以关闭变量。让数组=[]; tgt.accept ((node) => array.push(node))。这种方式通常不那么冗长。
    • @Bae,但据我所知here,该对象在 JS 中仍然可以用于双重调度。节点不是在访问者函数中使用“if (x instanceof Foo)”,而是在其接受方法中调用访问者.forFoo。简单命名的“visit()”方法将用于类型语言,例如访客.visit(Foo x)。对 Udi 来说,我链接的资源中的访问者确实知道树,并且他们返回值。我相信这是正确的。否则如何实现 EvalVisitor?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 2015-06-25
    相关资源
    最近更新 更多