访问者模式
目的是封装一些施加于某种数据结构元素之上的操做。一旦这些操做须要修改的话,接受这个操做的数据结构则能够保持不变。
问题提出
System.Collection命名空间下提供了大量集合操做对象。但大多数状况下处理的都是同类对象的汇集。换言之,在汇集上采起的操做都是一些针对同类型对象的同类操做。可是若是针对一个保存有不一样类型对象的汇集采起某种操做该怎么办呢?
粗看上去,这彷佛不是什么难题。但是若是须要针对一个包含不一样类型元素的汇集采起某种操做,而操做的细节根据元素的类型不一样而有所不一样时,就会出现必须对元素类型作类型判断的条件转移语句。这个时候,使用访问者模式就是一个值得考虑的解决方案。
访问者模式
访问者模式适用于数据结构相对未定的系统,它把数据结构和做用于结构上的操做之间的耦合解脱开,使得操做集合能够相对自由地演化。
数据结构的每个节点均可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操做。这样的过程叫作"双重分派"。节点调用访问者,将它本身传入,访问者则将某算法针对此节点执行。
双重分派意味着施加于节点之上的操做是基于访问者和节点自己的数据类型,而不单单是其中的一者。
java
定义:封装某些做用于某种数据结构中各元素的操做,它能够在不改变数据结构的前提下定义做用于这些元素的新的操做。算法
类型:行为类模式数据结构
类图:dom
元素Element:ide
package visitor; public interface Elements { public void accept(Visitor visitor); public void domethod(); }
元素的具体类 AdminElement:测试
package visitor; public class AdminElement implements Elements{ @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visit(this); } @Override public void domethod() { // TODO Auto-generated method stub System.out.println("visiting adminElement"); } }
元素具体类 customerElement:this
package visitor; public class CustomerElement implements Elements{ @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visit(this); } @Override public void domethod() { // TODO Auto-generated method stub System.out.println("visit customer function"); } }
访问者接口Visitor:spa
package visitor; public interface Visitor { public void visit(AdminElement adminElement ); public void visit(CustomerElement customerElement); }
访问者实现类AdminVisitor:code
package visitor; public class AdminVisitor implements Visitor{ @Override public void visit(AdminElement adminElement) { // TODO Auto-generated method stub adminElement.domethod(); } @Override public void visit(CustomerElement customerElement) { // TODO Auto-generated method stub System.out.println("admin cannot visit customer"); } }
访问者实现类customer:对象
package visitor; public class CustomerVisitor implements Visitor{ @Override public void visit(AdminElement adminElement) { // TODO Auto-generated method stub System.out.println("no permission ~!"); } @Override public void visit(CustomerElement customerElement) { // TODO Auto-generated method stub customerElement.domethod(); } }
客户端代码:
package visitor; import java.util.ArrayList; import java.util.List; public class MainFunction { public static void main(String[] args) { // TODO Auto-generated method stub List<Elements> list = new ArrayList<Elements>(); for(int i=0;i<10;i++) list.add(Creator.newElement()); AdminVisitor av = new AdminVisitor(); CustomerVisitor cv = new CustomerVisitor(); // adminVistor访问 for (Elements elements : list) { elements.accept(av); } System.out.println("-------------------------"); //customerVistor访问 for (Elements elements : list) { elements.accept(cv); } } }
建立测试对象类creator:
package visitor; import java.util.Random; public class Creator { public static Elements newElement() { Random r = new Random(); switch (r.nextInt(2)) { case 0: return new AdminElement(); case 1: return new CustomerElement(); default: return new AdminElement(); } } }