美丽的爪哇岛

访问者模式

2018-04-17  本文已影响7人  begonia_rich

Java的设计模式很多,以前看过很多遍,最近才搞懂了访问者模式,真是惭愧,看了一些github的源码有一些访问者模式的例子,由此写一个demo加深印象,共勉

提要

访问者模式最核心的点:分离数据和行为
注意它与模版方法模式的区别,一个是提到父类完成模版,另一个是将整个方法委托出去,灵活性更大,同时复杂度升高。

结构

主要有访问者(Visitor),被访问对象(Element)两个角色,被访问对象的行为被抽到了访问者中进行。

代码示例

抽象接口定义

/**
 * 访问者
 * @author xiezhengchao
 * @since 2018/4/17 18:16
 */
public interface Visitor{

    /**
     * 访问元素具体操作
     */
    void visit(ElementA elementA);

    void visit(ElementB elementB);

    /**
     * 抽象行为的入口
     */
    void go(Element element);

}

/**
 * 行为抽象,一般这个接口都是已有的
 * 
 * @author xiezhengchao
 * @since 2018/4/17 18:33
 */
public interface GoAble{

    /**
     * do it
     */
    void go();

}


/**
 * 待访问元素
 * @author xiezhengchao
 * @since 2018/4/17 18:17
 */
public interface Element extends GoAble{

    /**
     * 回调访问者,让访问者决定具体执行子对象的行为
     */
    void accept(Visitor visitor);

}

下面看具体实现


/**
 * 访问者实现
 */
public class DefaultVisitor implements Visitor{


    /**
     * 行为入口,由element触发
     */
    @Override
    public void go(Element element){
        // 直接去accept触发visit到我们自己的行为实现
        element.accept(this);
    }

    /**
     * 从不同的元素中获取信息 name()
     */
    @Override
    public void visit(ElementA elementA){
        print(elementA.name());
    }

    /**
     * 从不同的元素中获取信息 surname()
     */
    @Override
    public void visit(ElementB elementB){
        print(elementB.surname());
    }

    /**
     * 比如这是统一的处理方法流程
     */
    private void print(String str){
        System.out.println(str);
    }
}

/**
 * 让所有元素都有相同的行为,和模版方法是彻底不同的思路实现,这个模式明显更犀利
 *
 * @author xiezhengchao
 * @since 2018/4/17 18:32
 */
public abstract class AbstractElement implements Element{

    private Visitor visitor;

    public AbstractElement(Visitor visitor){
        this.visitor = visitor;
    }

    @Override
    public void go(){
        // 将抽象出去的行为 委托给访问者完成
        visitor.go(this);
    }

}

public class ElementA extends AbstractElement{

    public ElementA(Visitor visitor){
        super(visitor);
    }

    @Override
    public void accept(Visitor visitor){
        visitor.visit(this);
    }

    public String name(){
        return "I am A";
    }
}

public class ElementB extends AbstractElement{

    public ElementB(Visitor visitor){
        super(visitor);
    }

    @Override
    public void accept(Visitor visitor){
        visitor.visit(this);
    }

    public String surname(){
        return "I am sur B";
    }
}

接下来使用,使用起来简单明了


/**
 * 访问者模式
 * 1分离数据和行为
 * 2存在着相似的操作,避免重复代码
 *
 * @author xiezhengchao
 * @since 2018/4/17 18:20
 */
public class Client{

    public static void main(String[] args){

        Visitor visitor = new DefaultVisitor();

        // 通过访问者模式将数据和行为剥离,这看起来相当的明显,虽然还是调用的Element的方法,但是实际上方法是在访问者中进行,数据在元素中存储
        new ElementA(visitor).go();
        new ElementB(visitor).go();
    }

}

注释里已经把核心的功能描述的相当清楚了,这里不再赘述

总结

设计模式多种多样,平常用的多的也就那些,不怎么用,但是优秀的设计模式也值得多去回味思考。

源码地址

以上源码地址:https://github.com/znyh113too/vistor

上一篇 下一篇

猜你喜欢

热点阅读