设计模式(23)--访问者模式

xiaoxiao2021-02-28  87

访问者模式,用来解决多个访问者访问多个不同元素的问题。访问者模式引入了访问者角色和被访问者角色,不同访问者访问元素的方式不同。

举个例子(该例子来源于 《C#设计模式》刘伟 胡志刚 阎朝坤):

公司员工分为全职员工和兼职员工(这里员工就是被访问者),公司有财务部结算工资,人力资源部计算工作时长(这里财务部和人力资源部为访问者),于是就有了不同访问者访问不同被访问者的情况。

访问者模式UML类图如图:

示例代码:

抽象访问者:

/***** * 抽象访问者,财务部和人力资源部类的父类 * @author wjw * */ public abstract class Visitor { /***** * 访问者访问被访问者,所以应该有访问方法,那到底是定义一个抽象方法访问抽象被访问者 * 还是为每个具体访问者定义一个访问方法?其实都行,为了系统结构清晰最好各自定义,这里我做实验,用了一个方法 * */ public abstract void visitor(BeVisitored beVisitored); }

财务部和人力资源部两个具体访问者:

/***** * 财务部访问者 * @author wjw * */ public class CaiwuVisitor extends Visitor{ @Override public void visitor(BeVisitored beVisitored) { // TODO Auto-generated method stub if(beVisitored instanceof All){ All all = (All)beVisitored; //全职者被财务部访问 System.out.println("全职被访问者:" + all.getName() + "本月工资为:" + all.getMoney() + "元!"); }else if(beVisitored instanceof Part){ Part part = (Part)beVisitored; System.out.println("兼职被访问者:" + part.getName() + "本月工资为:" + part.getMoney() + "元!"); }else{ System.out.println("这里不该你访问!"); } } } /**** * 人力资源访问类 * @author wjw * */ public class RenliziyuanVisitor extends Visitor{ @Override public void visitor(BeVisitored beVisitored) { // TODO Auto-generated method stub // TODO Auto-generated method stub if(beVisitored instanceof All){ All all = (All)beVisitored; //全职者被财务部访问 System.out.println("全职被访问者:" + all.getName() + "本月工作时长为:" + all.getTime() + "小时!"); }else if(beVisitored instanceof Part){ Part part = (Part)beVisitored; System.out.println("兼职被访问者:" + part.getName() + "本月工资为:" + part.getTime() + "小时!"); }else{ System.out.println("这里不该你访问!"); } } }

被访问者接口:

/***** * 被访问者接口,全职员工和兼职员工实现该接口 * @author wjw * */ interface BeVisitored { //被访问者自然是接受访问了 void accept(Visitor visitor); } 全职员工和兼职员工两个具体被访问者:

/***** * 全职员工 * @author wjw * */ public class All implements BeVisitored{ private String name;//姓名 private int time;//int时常 private int money;//工资 public All(String name, int time, int money) { super(); this.name = name; this.time = time; this.money = money; } @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visitor(this); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTime() { return time; } public void setTime(int time) { this.time = time; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } }

/**** * 兼职员工类 * @author wjw * */ public class Part implements BeVisitored{ private String name;//姓名 private int time;//int时常 private int money;//工资 public Part(String name, int time, int money) { super(); this.name = name; this.time = time; this.money = money; } @Override public void accept(Visitor visitor) { // TODO Auto-generated method stub visitor.visitor(this); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTime() { return time; } public void setTime(int time) { this.time = time; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } } 访问辅助类:

/**** * 本类为“对象结构类”(这是一个专有名词,不必强要理解),也属于访问者模式一员,具有辅助访问功能: * 本类主要完成:将被访问者添加到集合中,便于访问者批量访问被访问者 * @author wjw * */ public class EmployeeUtils { private List<BeVisitored> beVisitors = new ArrayList<BeVisitored>(); /**** * 添加被访问者元素 */ public void addBeVisitor(BeVisitored beVisitored){ beVisitors.add(beVisitored); } /**** * 所有被访问者接受某特定访问者访问 */ public void aaccept(Visitor visitor){ Iterator<BeVisitored> iterator = beVisitors.iterator(); while(iterator.hasNext()){ BeVisitored beVisitor = iterator.next(); beVisitor.accept(visitor); } } } Main方法:

public class Main { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { //new两个全职员工 BeVisitored b1All = new All("王朕", 100, 5000); BeVisitored b2All = new All("王明明", 100, 5000); //new两个兼职员工 BeVisitored b1Part = new Part("窦唯", 100, 5000); BeVisitored b2Part = new Part("朴树", 100, 5000); //将员工放到集合中 EmployeeUtils eu = new EmployeeUtils(); eu.addBeVisitor(b1All); eu.addBeVisitor(b2All); eu.addBeVisitor(b1Part); eu.addBeVisitor(b2Part); //反射new具体访问者,通过辅助类访问所有被访问者 Class visitorClazz = Class.forName(ReadProperties.readProperties("visitor_name")); Visitor visitor = (Visitor)visitorClazz.newInstance(); eu.aaccept(visitor); } }

运行结果:

全职被访问者:王朕本月工作时长为:100小时! 全职被访问者:王明明本月工作时长为:100小时! 兼职被访问者:窦唯本月工资为:100小时! 兼职被访问者:朴树本月工资为:100小时!

示例代码说明:大多数说明都在类中注释了

访问者模式说明:访问者模式用来解决多个访问者访问多个被访问者的问题,所以,不同访问者面对不同被访问者有不同处理方式。而访问者模式恰恰用来解决这种问题。访问者模式如果扩展访问者容易扩展,但扩展被访问者需修改代码,这属于开闭原则倾斜行。

如有错误,欢迎指正

end

转载请注明原文地址: https://www.6miu.com/read-57317.html

最新回复(0)