访问者模式常用于:业务规则要求遍历多个不同的对象。基于这一点,我们来理解访问者模式,就要容易许多。
其定义为:Represent an operation to be performed on the element of an object structure. Visitors lets you define a new operation without change the classes of the elements on which it operates.通俗一点来说,一家超市是一个object,里面卖的商品是element,导购员就是visitor。超市没必要改变它所卖的商品的摆放规则,导购员就可以为有着不同消费需求的顾客,选购出他们所需要的产品。其实导购员选购的过程,就是在遍历这个超市的所有商品,这就回到了访问者模式设计的出发点上。
其通常的实现方式,如下面类图所示:
访问者模式中,有以下几个部分:
- 基本元素Element,通过accept()方法定义哪个访问者可以访问。
- 访问者Visitor,通过调用visit()方法的重载,在visit方法调用待访问的Element类的相关资源,达到访问效果。
其中ElementGenerator用于随机生成一批Element,用于测试Visitor类对其的访问效果.
测试形式:通过一个统一的Visitor类,可以访问到一批Element类中我们所关心的东西。
示例代码如下:
package song.visitMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Created by Song on 2016/10/28.
* 访问者模式
*/
//抽象元素类
abstract class Element{
//业务逻辑
public abstract void doSomething();
//定义外部访问接口
public abstract void accept(Ivisitor visitor);
}
/***************************************************************/
//具体的元素类1
class ConcreteClass1 extends Element{
@Override
public void doSomething() {
System.out.println("这是Element1");
}
@Override
public void accept(Ivisitor visitor) {
visitor.visit(this);
}
}
class ConcreteClass2 extends Element{
@Override
public void doSomething() {
System.out.println("这是Element2");
}
@Override
public void accept(Ivisitor visitor) {
visitor.visit(this);
}
}
/***************************************************************/
//访问者接口
interface Ivisitor{
//通过重载定义可以访问哪些对象
public void visit(ConcreteClass1 concreteClass);
public void visit(ConcreteClass2 concreteClass);
}
//具体的访问者
class Visitor implements Ivisitor{
public void visit(ConcreteClass1 concreteClass) {
//定义业务逻辑
concreteClass.doSomething();
}
public void visit(ConcreteClass2 concreteClass) {
//定义业务逻辑
concreteClass.doSomething();
}
}
/***************************************************************/
//生成不同的Element对象,用于测试
class ElementGenerator{
public static List<Element> generate(int num){
List<Element> list = new ArrayList<Element>();
Random rand = new Random();
while ((num--)>0){
if(rand.nextBoolean()){
list.add(new ConcreteClass1());
}else {
list.add(new ConcreteClass2());
}
}
return list;
}
}
/***************************************************************/
//场景类测试
public class Client {
public static void main(String [] args){
List<Element> list = ElementGenerator.generate(10);
Ivisitor visitor = new Visitor();
for(Element element:list){
element.accept(visitor);
}
}
}