本文内容来源于网络收集
作者:冰河
来源:冰河技术公众号
- 本章难度:★★☆☆☆
- 本章重点:用最简短的篇幅介绍访问者模式最核心的知识,理解访问者模式的设计精髓,并能够灵活运用到实际项目中,编写可维护的代码。
一、概述
表示一个作用于某对象结构中的各元素的操作。 可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
二、适用性
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
|