前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之访问者模式(行为型)

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

作者头像
SmileNicky
发布2019-03-20 11:54:12
5080
发布2019-03-20 11:54:12
举报
文章被收录于专栏:Nicky's blogNicky's blog

模式定义

访问者模式:表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。所以访问者模式是一种对象行为型模式。

模式角色

访问者模式包括如下角色:

  • Vistor(抽象访问者)
  • ConcreteVisitor(具体访问者)
  • Element(抽象元素)
  • ConcreteElement(具体元素)
  • ObjectStructure(对象结构)

模式分析

访问者模式的对象结构存储了不同类型的元素对象,以供不同的访问者访问

访问者模式包括了两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,一个是元素层级结构,提供了抽象元素和具体元素

相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同的访问者以不同访问方式访问。

典型代码:

抽象访问者类

代码语言:javascript
复制
public abstract class Visitor
{
	public abstract void visit(ConcreteElementA elementA);
	public abstract void visit(ConcreteElementB elementB);
	public void visit(ConcreteElementC elementC)
	{
		//元素ConcreteElementC操作代码
	}
} 

具体访问者类

代码语言:javascript
复制
public class ConcreteVisitor extends Visitor
{
	public void visit(ConcreteElementA elementA)
	{
		//元素ConcreteElementA操作代码
	}
	public void visit(ConcreteElementB elementB)
	{
		//元素ConcreteElementB操作代码
	}
} 

抽象元素类

代码语言:javascript
复制
public interface Element
{
	public void accept(Visitor visitor);
} 

具体元素类

代码语言:javascript
复制
public class ConcreteElementA implements Element
{
	public void accept(Visitor visitor)
	{
		visitor.visit(this);
	}
	
	public void operationA()
	{
		//业务方法
	}
} 

对象结构类

代码语言:javascript
复制
public class ObjectStructure
{
	private ArrayList list=new ArrayList();
	public void accept(Visitor visitor)
	{
		Iterator i=list.iterator();
		
		while(i.hasNext())
		{
			((Element)i.next()).accept(visitor);	
		}
	}
	public void addElement(Element element)
	{
		list.add(element);
	}
	public void removeElement(Element element)
	{
		list.remove(element);
	}
} 

模式例子

本例子来自《设计模式》一书

实例一:购物车 顾客在超市中将选择的商品,如苹果、图书等放在购物车中,然后到收银员处付款。在购物过程中,顾客需要对这些商品进行访问,以便确认这些商品的质量,之后收银员计算价格时也需要访问购物车内顾客所选择的商品。此时,购物车作为一个ObjectStructure(对象结构)用于存储各种类型的商品,而顾客和收银员作为访问这些商品的访问者,他们需要对商品进行检查和计价。不同类型的商品其访问形式也可能不同,如苹果需要过秤之后再计价,而图书不需要。使用访问者模式来设计该购物过程。

抽象的访问者类

代码语言:javascript
复制
public abstract class Visitor
{
	protected String name;
	
	public void setName(String name)
	{
		this.name=name;
	}
	
	public abstract void visit(Apple apple);
	
	public abstract void visit(Book book);
}

具体的访问者类:

代码语言:javascript
复制
public class Saler extends Visitor
{
	public void visit(Apple apple)
	{
		System.out.println("收银员" + name + "给苹果过秤,然后计算其价格。");
	}
	
	public void visit(Book book)
	{
		System.out.println("收银员" + name + "直接计算书的价格。");
	}
}
代码语言:javascript
复制
public class Customer extends Visitor
{
	public void visit(Apple apple)
	{
		System.out.println("顾客" + name + "选苹果。");
	}
	
	public void visit(Book book)
	{
		System.out.println("顾客" + name + "买书。");
	}
}

元素接口类:

代码语言:javascript
复制
public interface Product
{
	void accept(Visitor visitor);
}

具体的元素类:

代码语言:javascript
复制
public class Apple implements Product
{
  public void accept(Visitor visitor)
  {
      visitor.visit(this);
  }	
}
代码语言:javascript
复制
public class Book implements Product
{
  public void accept(Visitor visitor)
  {
      visitor.visit(this);
  }	
}

对象结构类:

代码语言:javascript
复制
import java.util.*;

public class BuyBasket
{
	private ArrayList list=new ArrayList();
	
	public void accept(Visitor visitor)
	{
		Iterator i=list.iterator();
		
		while(i.hasNext())
		{
			((Product)i.next()).accept(visitor);	
		}
	}
	
	public void addProduct(Product product)
	{
		list.add(product);
	}
	
	public void removeProduct(Product product)
	{
		list.remove(product);
	}
}

客户端类:

代码语言:javascript
复制
public class Client
{
	public static void main(String a[])
	{
		Product b1=new Book();
		Product b2=new Book();
		Product a1=new Apple();
		Visitor visitor;
		
        BuyBasket basket=new BuyBasket();
        basket.addProduct(b1);
        basket.addProduct(b2);
        basket.addProduct(a1);
        
        visitor=(Visitor)XMLUtil.getBean();
        
        visitor.setName("张三");
        	
        basket.accept(visitor);
	}
}
代码语言:javascript
复制
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil
{
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
	public static Object getBean()
	{
		try
		{
			//创建文档对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
		
			//获取包含类名的文本节点
			NodeList nl = doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();
            
            //通过类名生成实例对象并将其返回
            Class c=Class.forName(cName);
	  	    Object obj=c.newInstance();
            return obj;
           }   
           	catch(Exception e)
           	{
           		e.printStackTrace();
           		return null;
           	}
		}
}

config.xml

代码语言:javascript
复制
<?xml version="1.0"?>
<config>
    <className>Saler</className>
</config>

模式应用

  • java xml处理的DOM4j,通过访问者模式的方式来读取并解析XML文档,VisitorSupport是DOM4J提供的Visitor接口的默认适配器
代码语言:javascript
复制
public class MyVisitor extends VisitorSupport 
{
    public void visit(Element element)
    {
        System.out.println(element.getName());
    }
    public void visit(Attribute attr)
    {
        System.out.println(attr.getName());
    }
},

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年03月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 模式定义
  • 模式角色
  • 模式分析
  • 模式例子
  • 模式应用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档