美文网首页
访问者(Visitor)

访问者(Visitor)

作者: 非空白 | 来源:发表于2017-06-25 11:48 被阅读0次

    意图

    表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下,定义作用于这些元素的新操作。

    结构

    访问者结构图

    适用性

    • 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;
    • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类;
    • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。

    优缺点

    • 访问者模式使得易于增加新的操作,仅需增加一个新的访问者即可在一个对象结构上定义一个新的操作;
    • 相关的行为被集中在访问者中,无关的行为被分散到各自的访问者子类中;
    • 每增加一个新的Element类,就需要在Visitor及其子类中添加新的操作;
    • 通过类层次进行访问,可以访问具有不同父类的对象,可以对Visitor增加任意类型的对象;
    • 当访问者访问对象结构中每一个元素时,它能够积累状态;
    • 访问者通常需要访问每一个元素的内部状态,因此很可能会破坏元素的封装性。


    示例

    一个编译器将源代码转换为抽象语法树之后,需要对该抽象语法树中的各个节点(变量节点,赋值节点等)进行类型检查(TypeCheck)、格式打印(PrettyPrint)及扩展的各种操作。

    实现(C#)

    using System;
    
    public abstract class Node
    {
        public abstract void Accept(NodeVisitor visitor);
    }
    
    public class VariableRefNode : Node
    {
        public override void Accept(NodeVisitor visitor)
        {
            visitor.VisitVariableRefNode(this);
        }
    }
    
    public class AssignmentNode : Node
    {
        public override void Accept(NodeVisitor visitor)
        {
            visitor.VisitAssignmentNode(this);
        }
    }
    
    public abstract class NodeVisitor
    {
        public abstract void VisitVariableRefNode(VariableRefNode node);
        public abstract void VisitAssignmentNode(AssignmentNode node);
    }
    
    // 1. 类型检查
    public class TypeCheckingVisitor : NodeVisitor
    {
        public override void VisitVariableRefNode(VariableRefNode node)
        {
            Console.WriteLine("类型检查「变量表达式」..");
        }
    
        public override void VisitAssignmentNode(AssignmentNode node)
        {
            Console.WriteLine("类型检查「赋值表达式」..");
        }
    }
    
    // 2. 格式打印
    public class PrettyPrintingVisitor : NodeVisitor
    {
        public override void VisitVariableRefNode(VariableRefNode node)
        {
            Console.WriteLine("格式打印「变量表达式」..");
        }
    
        public override void VisitAssignmentNode(AssignmentNode node)
        {
            Console.WriteLine("格式打印「赋值表达式」..");
        }
    }
    
    public class App
    {
        public static void Main(string[] args)
        {
            // 模拟一个对象结构
            Node[] objectStructure = { new VariableRefNode(), new AssignmentNode() };
    
            // 1. 类型检查
            objectStructure.Accept(new TypeCheckingVisitor());
    
            // 2. 格式打印
            objectStructure.Accept(new PrettyPrintingVisitor());
        }
    }
    
    public static class NodeExtensions
    {
        public static void Accept(this Node[] nodes, NodeVisitor visitor)
        {
            foreach(Node node in nodes)
            {
                node.Accept(visitor);
            }
        }
    }
    
    // 控制台输出:
    //  类型检查「变量表达式」..
    //  类型检查「赋值表达式」..
    //  格式打印「变量表达式」..
    //  格式打印「赋值表达式」..
    

    相关文章

      网友评论

          本文标题:访问者(Visitor)

          本文链接:https://www.haomeiwen.com/subject/ohqlcxtx.html