现在的位置: 首页 > 综合 > 正文

设计模式26—设计模式之访问者模式(Visitor)(行为型)

2013年12月01日 ⁄ 综合 ⁄ 共 4029字 ⁄ 字号 评论关闭
文章目录

1.讲解访问者模式

1.1访问者模式定义

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

1.2访问者模式要点

访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。

1.3访问者模式示例图以及说明

 
1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口。
3.Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
4.ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
5.ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。

1.4访问者示例代码

package demo24.visitor.example3;
/**
 * 被访问的元素的接口
 */
public abstract class Element {
	/**
	 * 接受访问者的访问
	 * @param visitor 访问者对象
	 */
	public abstract void accept(Visitor visitor);
}
************************************************************************
package demo24.visitor.example3;
/**
 * 具体元素的实现对象
 */
public class ConcreteElementA extends Element {
	public void accept(Visitor visitor) {
		//回调访问者对象的相应方法
		visitor.visitConcreteElementA(this);
	}
	/**
	 * 示例方法,表示元素已有的功能实现
	 */
	public void opertionA(){
		//已有的功能实现
	}
}
***********************************************************************
package demo24.visitor.example3;
/**
 * 具体元素的实现对象
 */
public class ConcreteElementB extends Element {
	public void accept(Visitor visitor) {
		//回调访问者对象的相应方法
		visitor.visitConcreteElementB(this);
	}
	/**
	 * 示例方法,表示元素已有的功能实现
	 */
	public void opertionB(){
		//已有的功能实现
	}
}
***********************************************************************
package demo24.visitor.example3;
/**
 * 访问者接口
 */
public interface Visitor {
	/**
	 * 访问元素A,相当于给元素A添加访问者的功能
	 * @param elementA 元素A的对象
	 */
	public void visitConcreteElementA(ConcreteElementA elementA);
	/**
	 * 访问元素B,相当于给元素B添加访问者的功能
	 * @param elementB 元素B的对象
	 */
	public void visitConcreteElementB(ConcreteElementB elementB);
}
***********************************************************************
package demo24.visitor.example3;
/**
 * 具体的访问者实现
 */
public class ConcreteVisitor1 implements Visitor {
	public void visitConcreteElementA(ConcreteElementA element) {
		//把去访问ConcreteElementA时,需要执行的功能实现在这里
		//可能需要访问元素已有的功能,比如:
		element.opertionA();
	}
	public void visitConcreteElementB(ConcreteElementB element) {
		//把去访问ConcreteElementB时,需要执行的功能实现在这里
		//可能需要访问元素已有的功能,比如:
		element.opertionB();
	}
}
***********************************************************************
package demo24.visitor.example3;
/**
 * 具体的访问者实现
 */
public class ConcreteVisitor2 implements Visitor {
	public void visitConcreteElementA(ConcreteElementA element) {
		//把去访问ConcreteElementA时,需要执行的功能实现在这里
		//可能需要访问元素已有的功能,比如:
		element.opertionA();
	}
	public void visitConcreteElementB(ConcreteElementB element) {
		//把去访问ConcreteElementB时,需要执行的功能实现在这里
		//可能需要访问元素已有的功能,比如:
		element.opertionB();
	}
}
***********************************************************************
package demo24.visitor.example3;
import java.util.*;
/**
 * 对象结构,通常在这里对元素对象进行遍历,让访问者能访问到所有的元素
 */
public class ObjectStructure {
	/**
	 * 示意,表示对象结构,可以是一个组合结构或是集合
	 */
	private Collection<Element> col = new ArrayList<Element>();
	/**
	 * 示意方法,提供给客户端操作的高层接口
	 * @param visitor 客户端需要使用的访问者
	 */
	public void handleRequest(Visitor visitor){
		//循环对象结构中的元素,接受访问
		for(Element ele : col){
			ele.accept(visitor);
		}
	}
	/**
	 * 示意方法,组建对象结构,向对象结构中添加元素。
	 * 不同的对象结构有不同的构建方式
	 * @param ele 加入到对象结构的元素
	 */
	public void addElement(Element ele){
		this.col.add(ele);
	}
}
***********************************************************************
package demo24.visitor.example3;
public class Client {
	public static void main(String[] args) {
		// 创建ObjectStructure
		ObjectStructure os = new ObjectStructure();
		// 创建要加入对象结构的元素
		Element eleA = new ConcreteElementA();
		Element eleB = new ConcreteElementB();
		// 把元素加入对象结构
		os.addElement(eleA);
		os.addElement(eleB);

		// 创建访问者
		Visitor visitor = new ConcreteVisitor1();

		// 调用业务处理的方法
		os.handleRequest(visitor);
	}
}

1.5访问者模式优缺点

优点:
好的扩展性
好的复用性
分离无关行为
缺点:
对象结构变化很困难
破坏封装

1.6访问者模式使用情况

1) 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2) 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来 定义在一个类中。
3) 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4) 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好

1.7访问者模式本质

预留通路回调实现

2.访问者模式案例分析

这个模式,是我所遇到的比较复杂的模式,想不出一个合适的例子来,网上合适的例子很少,以后再补充。实际上示例代码就已经比较准确了,只是没有一个比较合适的例子来一一对应而已。

抱歉!评论已关闭.