访问者模式

∥☆過路亽.° 提交于 2020-02-14 11:36:30

访问者模式

访问者模式是23种设计模式中最复杂、最难理解的设计模式。访问者模式属于行为模式,将对象(被访问者)与操作(访问者)分离,适用于对象本身具有复杂结构且对象相对固定但需要频繁增加对于对象的操作的场景。访问者模式主要由被访问者和访问者组成,访问者对象通过visit方法访问被访问者对象,被访问者对象通过accept方法接受访问者的访问。具体的操作实现在访问者的visit方法中,被访问者的accept方法只用于控制访问者的对象结构访问次序和访问权限。 访问者模式中的被访问者有时配合组合模式来实现。

访问者模式用于编译器前端

访问者模式的一个典型的应用场景是编译器前端。编译的中间结果:抽象语法树(AST),是一个树形结构的复杂对象。做完词法分析和语法分析将高级语言程序转换为AST之后,需要对AST做多遍操作,包括但不限于:建立符号表、静态语法检查、转换至中间码。上述这些操作都需要遍历AST对象进行操作。使用观察者模式,将AST对象作为被访问者(配合组合模式),将编译器前端对AST的操作作为访问者,可以实现AST结构与AST操作的分离,便于功能扩展。下面以本科编译课程的作业为例说明访问者模式。由于代码过长,采用Github链接方式展示完整代码,以下代码仅为示例。

抽象语法树

AST类:decaf.tree.Tree.java. 抽象基类Tree定义了一个AST节点,各个具体的AST节点(例如TopLevel, ClassDef, MethodDef, ForLoop等等)以及抽象访问者基类Visitor作为Treepublic内部类存在。

package decaf.tree;

public abstract class Tree {
    public void accept(Visitor v) {
        v.visitTree(this);
    }

    public static class TopLevel extends Tree {

		public List<ClassDef> classes;
		public Class main;
		public GlobalScope globalScope;
		
		public TopLevel(List<ClassDef> classes, Location loc) {
			super(TOPLEVEL, loc);
			this.classes = classes;
		}

    	@Override
        public void accept(Visitor v) {
            v.visitTopLevel(this);
        }
    }
    
    ...

    public static abstract class Visitor {

        public Visitor() {
            super();
        }
        
        public void visitTopLevel(TopLevel that) {
            visitTree(that);
        }

        ...
    }
}

静态语法检查

静态语法检查类:TypeCheck.javaTypeCheck作为一个访问者类,实现了抽象访问者Tree.Visitor,通过visit*操作访问各种AST节点。

package decaf.typecheck;

public class TypeCheck extends Tree.Visitor {
    private ScopeStack table;

	private Stack<Tree> breaks;

	private Function currentFunction;

	public TypeCheck(ScopeStack table) {
		this.table = table;
		breaks = new Stack<Tree>();
	}

	public static void checkType(Tree.TopLevel tree) {
		new TypeCheck(Driver.getDriver().getTable()).visitTopLevel(tree);
	}

    @Override
	public void visitTopLevel(Tree.TopLevel program) {
		table.open(program.globalScope);
		for (Tree.ClassDef cd : program.classes) {
			cd.accept(this);
		}
		table.close();
	}

    ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!