访问者模式

概念

  封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

角色

先上一张图:
UML

抽象访问者:抽象类或者接口,声明访问者可以访问哪些元素
访问者:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。
抽象元素类:接口或者抽象类,声明接受哪一类访问者访问。
元素类:实现抽象元素类所声明的方法。
结构对象:一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等。

上代码

  就模拟一下文件访问操作。

抽象访问者
/**
 * 
 * 抽象访问者类:申明可以访问哪些元素
 *
 */
public interface Visiter {
	void visit(DocA doca);
	
	void Visit(DocB docb);
}
访问者
/**
 * 具体的访问者
 *
 */
public class VisiterA implements Visiter {

	@Override
	public void visit(DocA doca) {
		System.out.println("DocA's content is:" + doca.readDoc());
	}

	@Override
	public void Visit(DocB docb) {
		System.out.println("DocB's content is:" + docb.readDoc());
	}

}

抽象元素类
/**
 * 
 * 抽象元素类:声明 接受何种类型的访问。
 *
 */
public abstract class Doc {
	public abstract void accept(Visiter visiter);
	public abstract String readDoc();
}
具体的元素类

  这里可以把readDoc方法交由Visiter实现。

/**
 * 
 * 具体的元素类A(ConcreteElement)
 *
 */
public class DocA extends Doc {

	//使用accept,代表只有指定的visiter才能访问。
	@Override
	public void accept(Visiter visiter) {
		visiter.visit(this);
	}

	@Override
	public String readDoc() {
		return "This is DocA";
	}

}
/**
 * 具体的元素类B(ConcreteElement)
 *
 */
public class DocB extends Doc{

	@Override
	public void accept(Visiter visiter) {
		visiter.Visit(this);
	}

	@Override
	public String readDoc() {
		return "This is DocB";
	}

}
结构对象
/**
 * 
 *文件袋:结构对象,容纳元素
 */
public class DocBag {
	private List<Doc> docs = new ArrayList<>();
	
	public List<Doc> getList(){
		if(docs.size()==0){
			docs.add(new DocA());
			docs.add(new DocB());
		}
		return docs;
	}

}
客户端测试类
public class VisitClient {
	public static void main(String[] args) {
		DocBag bags = new DocBag();
		List<Doc> docs = bags.getList();
		
		VisiterA visiter = new VisiterA();
		
		for(Doc doc:docs){
			doc.accept(visiter);
		}
	}
}

结果

The End

  看完代码就发现了,访问者模式主要将数据结构与数据操作分离。但是这样不符合迪米特原则。

优点:
  1、可扩展性比较好,灵活。元素类可以通过接受不同的访问者来实现对不同操作的扩展。
  2、符合单一职责原则。

缺点
   1、具体元素对访问者公布细节,违反了迪米特原则。
  2、因为访问者对应着具体元素的操作,所以添加元素的话需要修改很多地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值