JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C++,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代表全部的正确,特此声明。若读者需要了解设原则、设计变化方向,环境相关等信息请查看设计模式开篇。
所有JAVA SCRIPT设计模式快捷连接:
创建型:(1) 抽象工厂 (2) 生成器 (3) 工厂方法 (4) 原型 (5) 单例
结构型:(6) 适配器 (7) 桥接 (8) 组合 (9) 装饰 (10) 外观 (11) 享元 (12) 代理
行为型:(13) 职责链 (14) 命令 (15) 解释器 (16) 迭代器 (17) 中介者 (18) 备忘录 (119) 观察者 (20) 状态 (21) 策略 (22) 模板方法 (23) 访问者
参与者:
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
不变元素Node,不同Visitor访问这些元素Node不同的操作。
考虑一个编译器,它将源程序表示为一个抽象语法树。该编译器需在抽象语法树上实施某些操作以进行“静态语义”分析,例如检查是否所有的变量都已经被定义了。它也需要生
成代码。因此它可能要定义许多操作以进行类型检查、代码优化、流程分析,检查变量是否在使用前被赋初值,等等。此外,还可使用抽象语法树进行优美格式打印、程序重构、代码植入以及对程序进行多种度量。
这些操作大多要求对不同的节点进行不同的处理。例如对代表赋值语句的结点的处理就不同于对代表变量或算术表达式的结点的处理。因此有用于赋值语句的类,有用于变量访问的类,还有用于算术表达式的类,等等。结点类的集合当然依赖于被编译的语言,但对于一个给定的语言其变化不大。
上面的框图显示了 Node类层次的一部分。这里的问题是,将所有这些操作分散到各种结点类中会导致整个系统难以理解、难以维护和修改。将类型检查代码与优美格式打印代码或流程分析代码放在一起,将产生混乱。此外,增加新的操作通常需要重新编译所有这些类。 如果可以独立地增加新的操作,并且使这些结点类独立于作用于其上的操作,将会更好一些。
要实现上述两个目标,我们可以将每一个类中相关的操作包装在一个独立的对象(称为 一个Visitor)中,并在遍历抽象语法树时将此对象传递给当前访问的元素。当一个元素“accepts”该访问者时,该元素向访问者发送一个包含自身类信息的请求。该请求同时也将该元素本身作为一个参数。然后访问者将为该元素执行该操作—这一操作以前是在该元素的类中的。 例如,一个不使用访问者的编译器可能会通过在它的抽象语法树上调用 TypeCheck操作对一个过程进行类型检查。每一个结点将对调用它的成员的TypeCheck以实现自身的TypeCheck(参见前面的类框图)。如果该编译器使用访问者对一个过程进行类型检查,那么它将会创建一个TypeCheckingVisitor对象,并以这个对象为一个参数在抽象语法树上调用Accept操作。每一个结点在实现Accept时将会回调访问者:一个赋值结点调用访问者的VisitAssignment操作,而一个变量引用将调用VisitVariableReference。以前类AssignmentNode的TypeCheck操作现在成为TypeCheckingVisitor的VisitAssignment操作。
为使访问者不仅仅只做类型检查,我们需要所有抽象语法树的访问者有一个抽象的父类NodeVisitor。NodeVisitor必须为每一个结点类定义一个操作。一个需要计算程序度量的应用
将定义NodeVisitor的新的子类,并且将不再需要在结点类中增加与特定应用相关的代码。Visitor模式将每一个编译步骤的操作封装在一个与该步骤相关的Visitor中(参见下图)。
使用Visitor模式,必须定义两个类层次:一个对应于接受操作的元素(Node层次)另一个对应于定义对元素的操作的访问者(NodeVisitor层次)。给访问者类层次增加一个新的子类即可创建一个新的操作。只要该编译器接受的语法不改变(即不需要增加新的Node子类),我们就可以简单的定义新的NodeVisitor子类以增加新的功能。
import Node from '../Node/Node.js';
export default class NodeVisitor {
constructor() {
}
VisitAssignment(Node)
{
}
VisitVariableRef(Node)
{
}
}
import NodeVisitor from '../NodeVisitor.js';
export default class TypeCheckingVisitor extends NodeVisitor {
constructor() {
super();
}
VisitAssignment(AssignmentNode)
{
console.log(` TypeCheckingVisitor VisitAssignment `);
}
VisitVariableRef(VariableRefNode)
{
console.log(` TypeCheckingVisitor VisitVariableRef `);
}
}
import NodeVisitor from '../NodeVisitor.js';
export default class CodeGeneratingVisitor extends NodeVisitor {
constructor() {
super();
}
VisitAssignment(AssignmentNode)
{
console.log(` CodeGeneratingVisitor VisitAssignment `);
}
VisitVariableRef(VariableRefNode)
{
console.log(` CodeGeneratingVisitor VisitVariableRef `);
}
}
import NodeVisitor from '../Visitor/NodeVisitor.js';
export default class Node {
constructor( ) {
}
Accept(NodeVisitor) {
}
}
import Node from '../Node.js';
export default class AssignmentNode extends Node {
name;
type;
value;
constructor(name,type,value) {
super();
this.name=name;
this.type=type;
this.value=value;
}
Accept(NodeVisitor) {
NodeVisitor.VisitAssignment(this);
}
}
import Node from '../Node.js';
export default class VariableRefNode extends Node {
name;
type;
value;
constructor(name,type,value) {
super();
this.name=name;
this.type=type;
this.value=value;
}
Accept(NodeVisitor) {
NodeVisitor.VisitVariableRef(this);
}
}
import VariableRefNode from './Node/impl/VariableRefNode.js';
import AssignmentNode from './Node/impl/AssignmentNode.js';
import CodeGeneratingVisitor from './Visitor/impl/CodeGeneratingVisitor.js';
import TypeCheckingVisitor from './Visitor/impl/TypeCheckingVisitor.js';
export default class Program {
treeNode = []; //语法树 结果集
constructor( ) {
let varANode = new AssignmentNode('aa', 'int', 9);
this.treeNode.push(varANode);
let refA =new VariableRefNode('bb', 'int', varANode);
this.treeNode.push(refA);
this.Accept(new TypeCheckingVisitor());
this.Accept(new CodeGeneratingVisitor());
}
Accept(visitor) {
for (let n = 0; n < this.treeNode.length; n++) {
let item = this.treeNode[n];
item.Accept(visitor);
}
}
}
测试结果:
TypeCheckingVisitor访问是状态
TypeCheckingVisitor.js:10 TypeCheckingVisitor VisitAssignment
TypeCheckingVisitor.js:15 TypeCheckingVisitor VisitVariableRef
CodeGeneratingVisitor.js:11 CodeGeneratingVisitor VisitAssignment
CodeGeneratingVisitor.js:16 CodeGeneratingVisitor VisitVariableRef
下载链接:https://pan.baidu.com/s/1XuPqp84cccBNVkbnMY3sKw
提取码:q2ut