设计模式学习笔记——访问者模式

访问者模式

访问者模式,封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。(行为类模式)

结构图


抽象访问者Visitor:抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的。

访问者ConcreteVisitor:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。

抽象元素类Element:接口或者抽象类,声明接受哪一个类访问者访问,程序上是通过accept方法中的参数来定义的。抽象方法分为:本身的业务逻辑和允许接受哪类访问者来访问。

元素类:实现抽象元素类所声明的accept方法,通常都是visitor.visit(this)。

结构对象ObjectStruture:一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器。

demo

一个简单的例子:
public class A {

	public void method1(){
		System.out.println("I am A");
	}
	
	public void method2(B b){
		b.show(this);
	}
	
}

public class B {

	public void show(A a){
		a.method1();
	}
	
}

public class Test {

	public static void main(String[] args) {
		A a = new A();
		a.method1();
		
		a.method2(new B());
	}
	
}
这里是两种打印方式,method1只A之间打印,method2是通过B来调用A的打印方法。这里B就是一个简单的访问者。

代码实现

抽象被访问者Element:
/**
 * 抽象元素类,被访问者
 *
 * @author xukai 2016年4月30日 下午10:42:18
 * 
 */
public abstract class Element {

	/**
	 * 接受访问
	 * @param visitor
	 */
	public abstract void accept(IVisitor visitor);

	public abstract void doSomething();
	
}
具体被访问者ConcreteElement:
/**
 * 具体元素类,被访问者
 *
 * @author xukai 2016年4月30日 下午10:46:09
 * 
 */
public class ConcreteElement1 extends Element {

	@Override
	public void accept(IVisitor visitor) {
		visitor.visit(this);
	}

	@Override
	public void doSomething() {
		System.out.println("元素1");
	}

}

/**
 * 具体元素类,被访问者
 *
 * @author xukai 2016年4月30日 下午10:46:30
 * 
 */
public class ConcreteElement2 extends Element {

	@Override
	public void accept(IVisitor visitor) {
		visitor.visit(this);
	}

	@Override
	public void doSomething() {
		System.out.println("元素2");
	}

}

抽象访问者IVisitor:
/**
 * 抽象访问者
 *
 * @author xukai 2016年4月30日 下午10:46:00
 * 
 */
public interface IVisitor {

	/**
	 * 访问元素1
	 * @param ele
	 */
	public void visit(ConcreteElement1 ele);
	
	/**
	 * 访问元素2
	 * @param ele
	 */
	public void visit(ConcreteElement2 ele);
	
}
具体访问者Visitor:
/**
 * 具体访问者,可以访问某个元素
 *
 * @author xukai 2016年4月30日 下午10:46:34
 * 
 */
public class Visitor implements IVisitor {

	@Override
	public void visit(ConcreteElement1 ele) {
		ele.doSomething();
	}

	@Override
	public void visit(ConcreteElement2 ele) {
		ele.doSomething();
	}

}

结构对象ObjectStruture:
package com.xk.day0430.visitor.demo;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 容器,装元素,即被访问者
 *
 * @author xukai 2016年4月30日 下午10:47:08
 * 
 */
public class ObjectStruture {

	public static List getList() {
		List list = new ArrayList();
		Random random = new Random();
		for (int i = 0; i < 10; i++) {
			int a = random.nextInt(100);
			if (a > 50) {
				list.add(new ConcreteElement1());
			} else {
				list.add(new ConcreteElement2());
			}
		}
		return list;
	}

}

客户端:
import java.util.List;

public class Client {

	public static void main(String[] args) {
		List<Element> list = ObjectStruture.getList();
		for (Element e : list) {
			e.accept(new Visitor());
		}
	}

}

总结

优点

符合单一职责原则:适用访问者模式时,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使访问者模式一方面符合单一职责原则,另一方面,被封装的操作通常是易变的,所以发生变化时,可以在不改变元素类本身的前提下,实现变化部分扩展。
扩展性好:元素可以通过接受不同的访问者来实现对不同操作的扩展。

缺点

当增加性的元素类比较困难。通过代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,即每增加一个元素类都需要修改访问者类(包括子类或实现类),修改起来相当麻烦。再元素类数据不确定的情况下,慎用访问者模式。如果一个项目基本功能确定了,元素类数据基本确定不变了,变得只是元素类内的操作,这个时候可以使用访问者模式对原来的代码进行重构一遍。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值