Java访问者模式(Visitor)

一、概述
      访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。
       实现的基本思路:在对象结构上添加一个方法,作为通用的方法,也就是可以代表要添加的功能,在这个方法中传入具体的实现新功能的对象。在对象实现的具体实现对象中实现这个方法,回调传入具体的实现新功能的对象,就相当于调用到新功能上了。访问者的功能:能给一系列对象透明的添加新功能,从而避免在维护期间对一系列对象进行修改,而且还能变相实现复用访问者所具有的功能。
二、结构
       抽象访问者(Visitor)角色:声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它;
      具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的方法接口,也就是抽象访问者所声明的各个访问操作。它影响到访问者访问到一个类后该干什么,要做什么事情;
      抽象节点(Node)角色:声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的,该方法接受一个访问者对象作为一个参数。并且声明了在该节点上可以进行的操作;
具体元素(Concrete Element)角色:实现抽象元素类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了,并实现该具体节点上可以进行的操作;
       结构对象(ObjectStructure)角色:可以遍历结构中的所有元素;可以提供一个高层次的接口让访问者对象可以访问每一个元素;可以设计成一个复合对象或者一个聚集,如List或Set。
三、示例程序
public interface Visitor {
	// 对应于NodeA的访问操作
	public void visit(NodeA node);

	// 对应于NodeB的访问操作
	public void visit(NodeB node);
}
public class VisitorA implements Visitor {

	@Override
	public void visit(NodeA node) {
		System.out.println(node.operation());
	}

	@Override
	public void visit(NodeB node) {
		System.out.println(node.operation());
	}
}
public class VisitorB implements Visitor {

	@Override
	public void visit(NodeA node) {
		System.out.println(node.operation());
	}

	@Override
	public void visit(NodeB node) {
		System.out.println(node.operation());
	}
}
public abstract class Node {
	//接受操作
	public abstract void accept(Visitor visitor);
	
	public abstract String operation();
}
public class NodeA extends Node {

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

	@Override
	public String operation() {
		return "NodeA...";
	}
}
public class NodeB extends Node {

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

	@Override
	public String operation() {
		return "NodeB...";
	}
}
import java.util.ArrayList;
import java.util.List;

public class ObjectStructure {
	private List<Node> nodes = new ArrayList<Node>();

	// 执行方法操作
	public void action(Visitor visitor) {
		for (Node node : nodes) {
			node.accept(visitor);
		}
	}

	// 添加一个新元素
	public void add(Node node) {
		nodes.add(node);
	}
}
public class Client {

	public static void main(String[] args) {
		// 创建一个结构对象
		ObjectStructure os = new ObjectStructure();
		// 给结构增加一个节点
		os.add(new NodeA());
		// 给结构增加一个节点
		os.add(new NodeB());
		// 创建一个访问者
		Visitor visitor = new VisitorA();
		os.action(visitor);
	}
}
NodeA...
NodeB...
四、优缺点
       优点
:1)良好的扩展性:能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能;2)良好的复用性:可以通过访问者来定义整个对象结构通用的功能,从而提高复用程度;3)分离无关行为:可以通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一;4)对于原来的类层次增加新的操作,仅仅需要实现一个具体访问者角色就可以了,而不必修改整个类层次。而且这样符合“开闭原则”的要求;5)每个具体的访问者角色都对应于一个相关操作,因此如果一个操作的需求有变,那么仅仅修改一个具体访问者角色,而不用改动整个类层次。
       缺点:1)对象结构变化很困难:不适用于对象结构中的类经常变化的情况,因为对象结构发生了改变,访问者的接口和访问者的实现都要发生相应的改变,代价太高,访问者角色不适合具体元素角色经常发生变化的情况;2)破坏封装:访问者模式通常需要对象结构开放内部数据给访问者和ObjectStructrue,这破坏了对象的封装性。访问者角色要执行与元素角色相关的操作,就必须让元素角色将自己内部属性暴露出来,而在java中就意味着其它的对象也可以访问。这就破坏了元素角色的封装性。3)在访问者模式中,元素与访问者之间能够传递的信息有限,这往往也会限制访问者模式的使用。
五、适用场景
       1)假如一个对象中存在着一些与本对象不相干(或者关系较弱)的操作,为了避免这些操作污染这个对象,则可以使用访问者模式来把这些操作封装到访问者中去;
       2)假如一组对象中,存在着相似的操作,为了避免出现大量重复的代码,也可以将这些重复的操作封装到访问者中去;
       3)定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好;
       4)当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值