设计模式之访问者模式(Java实现)

Visitor(访问者)

一、意图

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

二、结构

访问者模式的结构图如图7-48所示。 • Visitor (访问者)为该对象结构中ConcreteElement的每一个类声明一个Visit操 作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类,这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。 • ConcreteVisitor (具体访问者)实现每个有Visitor声明的操作,每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。 • Element (元素)定义以一个访问者为参数的Accept操作。 • ConcreteElement (具体元素)实现以一个访问者为参数的Accept操作。 • ObjectStructure (对象结构)能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个组合或者一个集合,如一个列表或一个无序集合。

三、适用性

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

四、实现

某图书管理系统中管理着两种类型的文献:图书和论文。现在要求统计所有馆藏文献的总页码(假设图书馆中有一本 540 页的图书和两篇各 25 页的论文,那么馆藏文献的总页码就是 590 页)。采用 Visitor(访问者)模式实现该要求,得到如图 6-1 所示的类图。 首先 定义图书馆访问者接口。

interface LibraryVisitor {
          
   
	void visit(Book p_book);
	void visit(Article p_article);
	void printSum();
}

然后 用图书馆总页数打印访问者去实现这个接口。

其次 定义图书文献接口。

interface LibraryItemInterface {
          
   
	void accept(LibraryVisitor visitor);
	public String getName();
	public String getAuthor();
}

再其次 分别用论文和图书来实现这个接口。

最后 测试一下。

public class Visitor {
          
   

	public static void main(String[] args) {
          
   
		// TODO Auto-generated method stub
		LibraryItemInterface book = new Book("储华","软件设计师教程",540); 
		LibraryItemInterface article1 = new Article("张三","关于人工智能...",1,26); 
		LibraryItemInterface article2 = new Article("李四","关于计算机系统结构...",27,52); 
		LibraryVisitor libraryVisitor = new LibrarySumPrintVisitor();
		book.accept(libraryVisitor);
		article1.accept(libraryVisitor);
		article2.accept(libraryVisitor);
		libraryVisitor.printSum();
	}

}

运行结果:

经验分享 程序员 微信小程序 职场和发展