大话设计模式—访问者模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。主要解决稳定的数据结构和易变的操作耦合问题。

大话设计模式中程杰老师给出的定义是,访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作

访问者模式结构图:

基本代码:

package com.visitor;
/** * Visitor类,为该对象结构中的ConcreteElement的每一个实现类声明一个visit操作 * @author LMB * */
public abstract class Visitor {

    public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
    public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);

}
package com.visitor;
/** * 具体访问者ConcreteVisitorA,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法 * 乃是对应于结构中对象的类 * @author LMB * */
public class ConcreteVisitorA extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println(concreteElementA.getClass() + "被" + this.getClass() + "访问");     
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println(concreteElementB.getClass() + "被" + this.getClass() + "访问");         
    }

}
package com.visitor;
/** * 具体访问者ConcreteVisitorB,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法 * 乃是对应于结构中对象的类 * @author LMB * */
public class ConcreteVisitorB extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
        System.out.println(concreteElementA.getClass() + "被" + this.getClass() + "访问");     
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
        System.out.println(concreteElementB.getClass() + "被" + this.getClass() + "访问");         
    }

}
package com.visitor;

public abstract class Element {

    public abstract void accept(Visitor visitor);

}
package com.visitor;
/** * 具体元素对象ConcreteElementA,实现接受访问者访问的accept()方法 * @author LMB * */
public class ConcreteElementA extends Element {

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

    //其它相关方法
    public void operationA(){}

}
package com.visitor;
/** * 具体元素对象ConcreteElementB,实现接受访问者访问的accept()方法 * @author LMB * */
public class ConcreteElementB extends Element {

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

    //其它相关方法
    public void operationB(){}

}
package com.visitor;

import java.util.ArrayList;
import java.util.List;
/** * ObjectStructure类,能每句它的元素,可以提供一个高层的接口以允许访问者访问它的元素 * @author LMB * */
public class ObjectStructure {

    private List<Element> elements = new ArrayList<Element>();

    //添加元素
    public void attach(Element element){
        elements.add(element);
    }

    //移除元素
    public void detach(Element element){
        elements.remove(element);
    }

    //元素接受访问者访问
    public void accept(Visitor visitor){
        for (Element e : elements) {
            e.accept(visitor);
        }
    }


}
package com.visitor;

public class VisitorPatternDemo {

    public static void main(String[] args) {

        ObjectStructure objectStructure = new ObjectStructure();

        //将需要被访问的element实例添加到数据结构ObjectStructure中
        objectStructure.attach(new ConcreteElementA());
        objectStructure.attach(new ConcreteElementB());

        ConcreteVisitorA concreteVisitorA = new ConcreteVisitorA();
        ConcreteVisitorB concreteVisitorB = new ConcreteVisitorB();

        //element接受访问者的访问
        objectStructure.accept(concreteVisitorA);
        objectStructure.accept(concreteVisitorB);
    }

}

运行结果:

以上的模式定义中,我们只列出了两种Element的实现,如果Element的实现不止这两种,而是可以有多种ConcreteElementA、ConcreteElementB、ConcreteElementC……,那就意味着Visitor类中的抽象方法就不可能稳定了,每增加一种Element实现就需要在Visitor类和它所有的实现类中都增加一个访问方法,这就不符合开放-封闭原则了。

由此,我们可以抽象出访问者模式的适用范围(使用场景)

1、访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化,所以适用于数据结构相对稳定的操作

2、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

3、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。

优点:

访问者模式的优点是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。

缺点:

使增加新的数据结构变得困难。

你可能感兴趣的:(设计模式,数据结构,访问者模式,visitor)