visitor

参考:http://en.wikipedia.org/wiki/Visitor_pattern

class=thumbimage

Example
The following example is in the Java programming language, and shows how the contents of a tree of nodes (in this case describing the components of a car) can be printed. Instead of creating "print" methods for each subclass (Wheel, Engine, Body, and Car), a single class (CarElementPrintVisitor) performs the required printing action. Because different subclasses require slightly different actions to print properly, CarElementDoVisitor dispatches actions based on the class of the argument passed to it.

alt=A Diagram of the Java Code Example.        I, the copyright holder of this work, hereby release it into the public domain.  This applies worldwide. In case this is not legally possible, I grant any entity the right to use this work for any purpose, without any conditions, unless such conditions are required by law.

interface CarElementVisitor {
    void visit(Wheel wheel);
    void visit(Engine engine);
    void visit(Body body);
    void visit(Car car);
}
interface CarElement {
    void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
class Wheel implements CarElement {
    private String name;
    public Wheel(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
class Engine implements CarElement {
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
class Body implements CarElement {
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
class Car implements CarElement{
    CarElement[] elements;
    public CarElement[] getElements() {
        return elements.clone(); // Return a copy of the array of references.
    }
    public Car() {
        this.elements = new CarElement[]
          { new Wheel("front left"), new Wheel("front right"),
            new Wheel("back left") , new Wheel("back right"),
            new Body(), new Engine() };
    }
    public void accept(CarElementVisitor visitor) { 
        for(CarElement element : this.getElements()) {
            element.accept(visitor);
        }
        visitor.visit(this); 
    }
}
class CarElementPrintVisitor implements CarElementVisitor {
    public void visit(Wheel wheel) {     
        System.out.println("Visiting "+ wheel.getName()
                            + " wheel");
    }
    public void visit(Engine engine) {
        System.out.println("Visiting engine");
    }
    public void visit(Body body) {
        System.out.println("Visiting body");
    }
    public void visit(Car car) {     
        System.out.println("Visiting car");
    }
}
class CarElementDoVisitor implements CarElementVisitor {
    public void visit(Wheel wheel) {
        System.out.println("Kicking my "+ wheel.getName() + " wheel");
    }
    public void visit(Engine engine) {
        System.out.println("Starting my engine");
    }
    public void visit(Body body) {
        System.out.println("Moving my body");
    }
    public void visit(Car car) {
        System.out.println("Starting my car");
    }
}
public class VisitorDemo {
    static public void main(String[] args){
        Car car = new Car();
        car.accept(new CarElementPrintVisitor());
        car.accept(new CarElementDoVisitor());
    }
}

### 使用 JSQLParser 的 Visitor 模式进行 SQL 解析 JSQLParser 提供了一种强大的机制来遍历和操作 SQL 抽象语法树 (AST),即通过 `Visitor` 接口。此接口允许开发者创建自定义访问者类,用于处理特定类型的 SQL 节点。 为了实现 `Visitor` 模式的功能,在编写代码时通常会继承 `ExpressionVisitorAdapter` 或 `StatementVisitorAdapter` 类之一,这两个适配器实现了所有的方法但不做任何具体的操作,因此可以只重写感兴趣的方法[^1]。 下面是一个简单的例子展示如何利用 `Visitor` 来查找并打印所有表名: ```java import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.util.TablesNamesFinder; public class TablePrinter { public static void main(String[] args) throws JSQLParserException { Statement statement = CCJSqlParserUtil.parse("SELECT * FROM my_table WHERE id=1"); TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); List<String> tableList = tablesNamesFinder.getTableList(statement); System.out.println(tableList); // 输出: [my_table] // 自定义 visitor 实现 MyCustomVisitor visitor = new MyCustomVisitor(); statement.accept(visitor); } } class MyCustomVisitor extends ExpressionVisitorAdapter implements StatementVisitor { @Override public void visit(net.sf.jsqlparser.schema.Table table){ System.out.println("Visited table name:" + table.getName()); } // 需要覆盖其他必要的visit方法... } ``` 在这个例子中,`MyCustomVisitor` 继承了两个适配器类,并覆写了其中一部分方法以便于当遇到表格节点(`Table`)的时候能够执行某些逻辑——这里只是简单地输出表的名字。对于更复杂的场景,则可能还需要进一步扩展这个类以满足需求[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值