第23章 访问者模式

本文内容来源于网络收集

作者:冰河
来源:冰河技术公众号

  • 本章难度:★★☆☆☆
  • 本章重点:用最简短的篇幅介绍访问者模式最核心的知识,理解访问者模式的设计精髓,并能够灵活运用到实际项目中,编写可维护的代码。

一、概述

表示一个作用于某对象结构中的各元素的操作。 可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

二、适用性

1.一个对象结构包含很多类对象,它们有不同的接口,并且需要对这些对象实施一些依赖于其具体类的操作。

2.需要对一个对象结构中的对象进行很多不同的操作,并且这些操作不相关,并且需要避免这些操作“污染”这些对象的类。 Visitor设计模式可以将相关的操作集中起来定义在一个类中。 当该对象结构被很多应用共享时,用Visitor模式可以让每个应用仅包含需要用到的操作。

3.定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。 改变对象结构类需要重新定义对所有访问者的接口,这可能需要很大的代价。 如果对象结构类经常改变,那么可能还是在这些类中定义这些操作比较好。

三、参与者

1.Visitor 为该对象结构中ConcreteElement的每一个类声明一个Visit操作。 该操作的名字和特征标识了发送Visit请求给该访问者的哪个类。 这使得访问者可以确定是哪个类正在被访问。 这样访问者就可以通过该元素的特定接口直接访问它。

2.ConcreteVisitor 实现每个由Visitor声明的操作。 每个操作实现本算法的一部分,而该算法的一部分对应结构中对象的类。 ConcreteVisitor为该算法提供了上下文并存储它的局部状态。 这一状态常常在遍历该结构的过程中累积结果。

3.Element 定义一个Accept操作,它以一个访问者为参数。

4.ConcreteElement 实现Accept操作,该操作以一个访问者为参数。

5.ObjectStructure 能枚举它的元素。 可以提供一个高层的接口以允许该访问者访问它的元素。 可以是一个列表或是一个集合,如一个列表或一个无序集合。

四、类图


五、示例

Visitor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description Visitor
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public interface Visitor {
    void visitString(StringElement stringE);
    void visitFloat(FloatElement floatE);
    void visitCollection(Collection collection);
}

ConcreteVisitor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description ConcreteVisitor
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public class ConcreteVisitor implements Visitor {

    @Override
    public void visitString(StringElement stringE) {
        System.out.println(stringE.getSe());
    }

    @Override
    public void visitFloat(FloatElement floatE) {
        System.out.println(floatE.getFe());
    }

    @Override
    public void visitCollection(Collection collection) {
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            Object o = iterator.next();
            if (o instanceof Visitable) {
                ((Visitable)o).accept(this);
            }
        }
    }
}

Element

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description Element
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public interface Visitable {
    void accept(Visitor visitor);
}

ConcreteElement

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description ConcreteElement
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public class FloatElement implements Visitable {

    private Float fe;

    public FloatElement(Float fe) {
        this.fe = fe;
    }

    public Float getFe() {
        return this.fe;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visitFloat(this);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description ConcreteElement
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public class StringElement implements Visitable{

    private String se;

    public StringElement(String se) {
        this.se = se;
    }

    public String getSe() {
        return this.se;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visitString(this);
    }
}

Test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * @author binghe(微信 : hacker_binghe)
 * @version 1.0.0
 * @description 测试类
 * @github https://github.com/binghe001
 * @copyright 公众号: 冰河技术
 */
public class Test {
    public static void main(String[] args) {
        Visitor visitor = new ConcreteVisitor();
        StringElement se = new StringElement("abc");
        se.accept(visitor);

        FloatElement fe = new FloatElement(new Float(1.5));
        fe.accept(visitor);
        System.out.println("===========");
        List<Visitable> result = new ArrayList();
        result.add(new StringElement("abc"));
        result.add(new StringElement("abc"));
        result.add(new StringElement("abc"));
        result.add(new FloatElement(new Float(1.5)));
        result.add(new FloatElement(new Float(1.5)));
        result.add(new FloatElement(new Float(1.5)));
        visitor.visitCollection(result);
    }
}

Result

1
2
3
4
5
6
7
8
9
abc
1.5
===========
abc
abc
abc
1.5
1.5
1.5