访问者模式
1.定义
表示一个作用于某对象结构中的个元素的操作,它可以使你在不改变个元素的类的前提下定义作用于这些元素的新操作。
2.示例代码
/** * 访问组合对象结构的访问者接口 */ public interface Visitor { /** * 访问组合对象,相当于给组合对象添加访问者的功能 * @param composite 组合对象 */ public void visitComposite(Composite composite); /** * 访问叶子对象,相当于给叶子对象添加访问者的功能 * @param leaf 叶子对象 */ public void visitLeaf(Leaf leaf); }
/** * 抽象的组件对象,相当于访问者模式中的元素对象 */ public abstract class Component { /** * 接受访问者的访问 * @param visitor 访问者对象 */ public abstract void accept(Visitor visitor); /** * 向组合对象中加入组件对象 * @param child 被加入组合对象中的组件对象 */ public void addChild(Component child) { // 缺省实现,抛出例外,叶子对象没这个功能,或子组件没有实现这个功能 throw new UnsupportedOperationException("对象不支持这个功能"); } /** * 从组合对象中移出某个组件对象 * @param child 被移出的组件对象 */ public void removeChild(Component child) { // 缺省实现,抛出例外,叶子对象没这个功能,或子组件没有实现这个功能 throw new UnsupportedOperationException("对象不支持这个功能"); } /** * 返回某个索引对应的组件对象 * @param index 需要获取的组件对象的索引,索引从0开始 * @return 索引对应的组件对象 */ public Component getChildren(int index) { throw new UnsupportedOperationException("对象不支持这个功能"); } }
/** * 组合对象,可以包含其它组合对象或者叶子对象, * 相当于访问者模式的具体Element实现对象 * public class Composite extends Component{ public void accept(Visitor visitor) { //回调访问者对象的相应方法 visitor.visitComposite(this); //循环子元素,让子元素也接受访问 for(Component c : childComponents){ //调用子对象接受访问,变相实现递归 c.accept(visitor); } } /** * 用来存储组合对象中包含的子组件对象 */ private List<Component> childComponents = new ArrayList<Component>(); /** * 组合对象的名字 */ private String name = ""; /** * 构造方法,传入组合对象的名字 * @param name 组合对象的名字 */ public Composite(String name){ this.name = name; } public void addChild(Component child) { childComponents.add(child); } public String getName() { return name; } }
/** * 叶子对象,相当于访问者模式的具体Element实现对象 */ public class Leaf extends Component{ public void accept(Visitor visitor) { //回调访问者对象的相应方法 visitor.visitLeaf(this); } /** * 叶子对象的名字 */ private String name = ""; /** * 构造方法,传入叶子对象的名字 * @param name 叶子对象的名字 */ public Leaf(String name){ this.name = name; } public String getName() { return name; } }
/** * 具体的访问者,实现:输出对象的名称,在组合对象的名称前面添加"节点:", * 在叶子对象的名称前面添加"叶子:" */ public class PrintNameVisitor implements Visitor { public void visitComposite(Composite composite) { //访问到组合对象的数据 System.out.println("节点:"+composite.getName()); } public void visitLeaf(Leaf leaf) { //访问到叶子对象的数据 System.out.println("叶子:"+leaf.getName()); } }
/** * 对象结构,通常在这里对元素对象进行遍历,让访问者能访问到所有的元素 */ public class ObjectStructure { /** * 表示对象结构,可以是一个组合结构 */ private Component root = null; /** * 提供给客户端操作的高层接口 * @param visitor 客户端需要使用的访问者 */ public void handleRequest(Visitor visitor){ //让组合对象结构中的根元素,接受访问 //在组合对象结构中已经实现了元素的遍历 if(root!=null){ root.accept(visitor); } } /** * 传入组合对象结构 * @param ele 组合对象结构 */ public void setRoot(Component ele){ this.root = ele; } }
public class Client { public static void main(String[] args) { //定义所有的组合对象 Component root = new Composite("服装"); Component c1 = new Composite("男装"); Component c2 = new Composite("女装"); //定义所有的叶子对象 Component leaf1 = new Leaf("衬衣"); Component leaf2 = new Leaf("夹克"); Component leaf3 = new Leaf("裙子"); Component leaf4 = new Leaf("套装"); //按照树的结构来组合组合对象和叶子对象 root.addChild(c1); root.addChild(c2); c1.addChild(leaf1); c1.addChild(leaf2); c2.addChild(leaf3); c2.addChild(leaf4); //创建ObjectStructure ObjectStructure os = new ObjectStructure(); os.setRoot(root); //调用ObjectStructure来处理请求功能 Visitor psVisitor = new PrintNameVisitor(); os.handleRequest(psVisitor); } }
/* *要实现这个功能,在组合对象结构中去遍历子对象的方式就比较难于实现,因为要输出这个树形结构,需要控制每个对象在输出的时候,向后的退格数量,这个需要在对象结构的循环中来控制,这种功能可以选择在访问者当中去遍历对象结构。 *来改造上面的示例,看看通过访问者来遍历元素如何实现这样的功能。 *首先在Composite的accept实现中去除掉递归调用子对象的代码,同时添加一个让访问者访问到其所包含的子对象的方法,示例代码如下: */ public class Composite extends Component{ //其它相同部分就省略了,只看变化的方法 public void accept(Visitor visitor) { //回调访问者对象的相应方法 visitor.visitComposite(this); } public List<Component> getChildComponents() { return childComponents; } } /** * 具体的访问者,实现:输出组合对象自身的结构 */ public class PrintStructVisitor implements Visitor { /** * 用来累计记录对象需要向后退的格 */ private String preStr = ""; public void visitComposite(Composite composite) { //先把自己输出去 System.out.println(preStr+"+"+composite.getName()); //如果还包含有子组件,那么就输出这些子组件对象 if(composite.getChildComponents()!=null){ //然后添加一个空格,表示向后缩进一个空格 preStr+=" "; //输出当前对象的子对象了 for(Component c : composite.getChildComponents()){ //递归输出每个子对象 c.accept(this); } //把循环子对象所多加入的一个退格给去掉 preStr = preStr.substring(0,preStr.length()-1); } } public void visitLeaf(Leaf leaf) { //访问到叶子对象的数据 System.out.println(preStr+"-"+leaf.getName()); } } /*客户端测试*/ public class Client { public static void main(String[] args) { //定义所有的组合对象过程跟上一个client是一样的,这里省略了 //调用根元素的方法来接受请求功能 Visitor psVisitor = new PrintStructVisitor(); root.accept(psVisitor); } }
3.实际应用
访问者模式能给一系列对象,透明的添加新功能。从而避免在维护期间,对这一系列对象进行修改,而且还能变相实现复用访问者所具有的功能。由于是针对一系列对象的操作,这也导致,如果只想给一系列对象中的部分对象添加功能,就会有些麻烦;而且要始终能保证把这一系列对象都要调用到,不管是循环也好,还是递归也好,总之要让每个对象都要被访问到。
- 如果想对一个对象结构,实施一些依赖于对象结构中的具体类的操作,可以使用访问者模式
- 如果想对一个对象结构中的各个元素,进行很多不同的而且不相关的操作,为了避免这些操作使得类变得杂乱,可以使用访问者模式,把这些操作分散到不同的访问者对象中去,每个访问者对象实现同一类功能
- 如果对象结构很少变动,但是需要经常给对象结构中的元素对象定义新的操作,可以使用访问者模式
访问者模式的本质:预留通路,回调实现
相关推荐
设计模式 - 访问者模式
JAVA-设计模式-行为型模式-访问者模式
设计模式-访问者模式(讲解及其实现代码)
c++设计模式-行为型模式-访问者模式;qt工程;c++简单源码; 访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新...
ios 平台实现设计模式-访问者模式,以最简单的代码实现访问者模式讲解,主旨在于了解访问者模式,博客:http://blog.sina.com.cn/s/blog_161d504630102wwxe.html
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段...
java常用设计模式-访问者模式
PPT内容包括:内附代码,实例,方便理解。 继承、封装、多态、UML 设计模式02 设计模式03-创建型模式 ...设计模式16-策略模式、模板方法、访问者 此PPT实例便于理解,对于深入理解OO思想有很大帮助。
设计模式 -访问者(Visitor)模式详解和应用.pdf
设计模式专题之(二十)访问者模式--设计模式访问者模式示例代码(python--c++)
访问者模式的简单介绍,计算机相关专业本科生,课程汇报
设计模式C++学习之访问者模式(Visitor)
5.11 VISITOR(访问者)—对象行为型模式 218 5.12 行为模式的讨论 228 5.12 1 封装变化 228 5.12.2 对象作为参数 228 5.12.3 通信应该被封装还是被分布 229 5.12.4 对发送者和接收者解耦 229 5.12.5 总结 231 第 6 ...
Visitor(访问者模式)属于行为型模式。意图:表示一个作用于某对象结构中的各元素的操作。
创建型模式,共五种:工厂方法模式、抽象工厂模式、...行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
访问者模式,你绝对会用到的模式,值得学习,通俗易懂的实例,原理和运用都说明白了。
java设计模式之访问者模式,通过实际例子说明访问者模式原理和适用场景;
设计模式之访问者模式Java版本的实现和UML类图
C#面向对象设计模式纵横谈(24):(行为型模式) Visitor 访问者模式
【例4.5】访问者模式-计算机部件销售软件 【例4.6】命令模式-室内温度控制 【例4.7】命令模式-室内温度控制-2个GUI 【例4.8】命令模式-室内温度控制-3个GUI 【例4.10】中介者模式-旅游信息共享 ...