22. 访问者模式(Visitor)
22. 访问者模式(Visitor)
问题:想在不修改对象结构的前提下,为其增加新操作。
核心:把操作从对象结构中分离出来,放到访问者中。
class NumberNode {
constructor(value) { this.value = value; }
accept(visitor) { return visitor.visitNumber(this); }
}
class StringNode {
constructor(value) { this.value = value; }
accept(visitor) { return visitor.visitString(this); }
}
class TypeVisitor {
visitNumber(node) { return `数字: ${node.value}`; }
visitString(node) { return `字符串: "${node.value}"`; }
}
class LengthVisitor {
visitNumber(node) { return String(node.value).length; }
visitString(node) { return node.value.length; }
}
const nodes = [new NumberNode(42), new StringNode('hello')];
nodes.forEach(n => console.log(n.accept(new TypeVisitor())));
// 数字: 42
// 字符串: "hello"
nodes.forEach(n => console.log(n.accept(new LengthVisitor())));
// 2
// 5package visitor
import (
"fmt"
"strconv"
)
type Visitor interface {
VisitNumber(n *NumberNode) string
VisitString(s *StringNode) string
}
type Node interface {
Accept(v Visitor) string
}
type NumberNode struct{ Value int }
func (n *NumberNode) Accept(v Visitor) string { return v.VisitNumber(n) }
type StringNode struct{ Value string }
func (s *StringNode) Accept(v Visitor) string { return v.VisitString(s) }
type TypeVisitor struct{}
func (t TypeVisitor) VisitNumber(n *NumberNode) string {
return fmt.Sprintf("数字: %d", n.Value)
}
func (t TypeVisitor) VisitString(s *StringNode) string {
return fmt.Sprintf("字符串: \"%s\"", s.Value)
}
type LengthVisitor struct{}
func (l LengthVisitor) VisitNumber(n *NumberNode) string {
return strconv.Itoa(len(strconv.Itoa(n.Value)))
}
func (l LengthVisitor) VisitString(s *StringNode) string {
return strconv.Itoa(len(s.Value))
}