Visitor模式,在不修改已有程序结构的前提下,通过添加额外的“访问者”来完成对已有代码功能的提升。
interface
Visitor
...
{
void visit(Gladiolus g);
void visit(Runuculus r);
void visit(Chrysanthemum c);
}


interface
Flower
...
{
void accept(Visitor v);
}

//
concrete element

class
Gladiolus
implements
Flower
...
{

public void accept(Visitor v) ...{ v.visit(this);}
}


class
Runuculus
implements
Flower
...
{

public void accept(Visitor v) ...{ v.visit(this);}
}


class
Chrysanthemum
implements
Flower
...
{

public void accept(Visitor v) ...{ v.visit(this);}
}

//
concrete visitor

class
StringVal
implements
Visitor
...
{
String s;

public String toString() ...{ return s; }

public void visit(Gladiolus g) ...{
s = "Gladiolus";
}


public void visit(Runuculus r) ...{
s = "Runuculus";
}


public void visit(Chrysanthemum c) ...{
s = "Chrysanthemum";
}
}

//
concrete visitor

class
Bee
implements
Visitor
...
{

public void visit(Gladiolus g) ...{
System.out.println("Bee and Gladiolus");
}


public void visit(Runuculus r) ...{
System.out.println("Bee and Runuculus");
}


public void visit(Chrysanthemum c) ...{
System.out.println("Bee and Chrysanthemum");
}
}

//
这是一个对象生成器

class
FlowerGenerator
...
{
private static Random rand = new Random();

public static Flower newFlower() ...{

switch(rand.nextInt(3)) ...{
default:
case 0: return new Gladiolus();
case 1: return new Runuculus();
case 2: return new Chrysanthemum();
}
}
}

//
客户测试程序

public
class
BeeAndFlowers
extends
TestCase
...
{


/**//*
首先在客户端先获得一个具体的访问者角色
遍历对象结构
对每一个元素调用accept方法,将具体访问者角色传入
这样就完成了整个过程
*/
List flowers = new ArrayList();

public BeeAndFlowers() ...{
for(int i = 0; i < 10; i++)
flowers.add(FlowerGenerator.newFlower());
}

Visitor sval ;

public void test() ...{
sval = new StringVal();
Iterator it = flowers.iterator();

while(it.hasNext()) ...{
((Flower)it.next()).accept(sval);
System.out.println(sval);
}
}


public static void main(String args[]) ...{
junit.textui.TestRunner.run(BeeAndFlowers.class);
}

}
Visitor模式的组成结构:
1) 访问者角色(Visitor):声明一个访问接口。接口的名称和方法的参数标识了向访问者发送请求的元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
2) 具体访问者角色(Concrete Visitor):实现访问者角色(Visitor)接口
3) 元素角色(Element):定义一个Accept操作,它以一个访问者为参数。
4) 具体元素角色(Concrete Element):实现元素角色(Element)接口。
5) 对象结构角色(Object Structure):这是使用Visitor模式必须的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口允许访问者角色访问它的元素;可以是一个组合(组合模式)或是一个集合,如一个列表或一个无序集合。
类图如下:
|
代码例子:




























































































































