`

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

阅读更多

访问者模式

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.实际应用

       访问者模式能给一系列对象,透明的添加新功能。从而避免在维护期间,对这一系列对象进行修改,而且还能变相实现复用访问者所具有的功能。由于是针对一系列对象的操作,这也导致,如果只想给一系列对象中的部分对象添加功能,就会有些麻烦;而且要始终能保证把这一系列对象都要调用到,不管是循环也好,还是递归也好,总之要让每个对象都要被访问到。
  • 如果想对一个对象结构,实施一些依赖于对象结构中的具体类的操作,可以使用访问者模式
  • 如果想对一个对象结构中的各个元素,进行很多不同的而且不相关的操作,为了避免这些操作使得类变得杂乱,可以使用访问者模式,把这些操作分散到不同的访问者对象中去,每个访问者对象实现同一类功能
  • 如果对象结构很少变动,但是需要经常给对象结构中的元素对象定义新的操作,可以使用访问者模式
访问者模式的本质:预留通路,回调实现

 

 

分享到:
评论

相关推荐

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 在C++中,这些设计模式通常通过面向对象的特性,如继承、封装和多态来实现...

    JAVA-设计模式-行为型模式-访问者模式

    JAVA-设计模式-行为型模式-访问者模式

    c++设计模式-行为型模式-访问者模式

    c++设计模式-行为型模式-访问者模式;qt工程;c++简单源码; 访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新...

    设计模式-访问者模式

    ios 平台实现设计模式-访问者模式,以最简单的代码实现访问者模式讲解,主旨在于了解访问者模式,博客:http://blog.sina.com.cn/s/blog_161d504630102wwxe.html

    java设计模式-访问者模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段...

    设计模式 - 访问者模式

    访问者模式(Visitor Pattern)是一种行为设计模式,它使你能在不修改对象结构的前提下向其添加新的操作。这种模式常用于处理具有相同接口或抽象类的对象结构,使得可以在不改变原有结构的基础上增加功能,实现对...

    C++设计模式--基于Qt4开源跨平台开发框架

    行为型模式如观察者模式(Observer)、策略模式(Strategy)和访问者模式(Visitor),关注对象之间的交互和责任分配。 在C++中,设计模式的应用通常涉及到面向对象编程的特性,如继承、封装和多态。Qt4框架则为...

    设计模式-访问者模式(讲解及其实现代码)

    访问者模式是一种行为设计模式,它允许在不修改对象结构的情况下向对象添加新的操作。这种模式的核心思想是将数据结构与算法分离,使得算法可以在不改变对象结构的前提下增加对对象的操作。 在软件开发中,有时我们...

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    ### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 引言 设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。GoF(Gang of Four)所提出的23种设计模式,被认为是面向对象...

    设计模式课件大全

    PPT内容包括:内附代码,实例,方便理解。 继承、封装、多态、UML 设计模式02 设计模式03-创建型模式 ...设计模式16-策略模式、模板方法、访问者 此PPT实例便于理解,对于深入理解OO思想有很大帮助。

    java设计模式---诙谐易懂版

    5. 文件中提到的24种设计模式,涵盖了大多数常用的模式。例如,代理模式(Proxy Pattern)、单例模式(Singleton Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory Pattern)、...

    软件设计与体系结构-设计模式-访问者模式-ppt制作

    访问者模式(Visitor Pattern)是软件工程领域中一种重要的设计模式,主要用于处理数据结构中元素的操作问题。该模式的核心思想在于将数据操作与数据结构本身相分离,通过这种方式,可以在不改变数据结构的前提下...

    设计模式精解-GoF 23种设计模式解析附C++.pdf

    ### 设计模式精解——GoF 23种设计模式解析及C++实现 #### 0. 引言 设计模式作为面向对象编程的核心组成部分,是软件开发者在长期实践中总结出来的最佳实践。通过深入理解这些设计模式,我们可以更好地进行面向...

    设计模式精解-GoF23种设计模式解析附C++实现源码

    - 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它可以在不改变各元素类的前提下定义作用于这些元素的新操作。 C++实现源码提供了具体编程环境下的应用实例,帮助读者更好地理解和应用这些...

    Java设计模式----通俗易懂版

    - 访问者模式:表示一个作用于某对象结构中的各元素的操作,它可以在不改变各元素的类的前提下定义新的操作。 通过这个"通俗易懂版"的学习资源,你将能够深入理解每种设计模式的原理,掌握如何在实际项目中应用...

    设计模式精解-GoF 23种设计模式解析附C++实现源码.pdf

    ### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 0. 引言 设计模式是软件工程领域的一个重要概念,它提供了一种解决常见问题的方法论。GoF(Gang of Four)所提出的23种设计模式被视为面向对象设计的...

    java常用设计模式-访问者模式

    访问者模式(Visitor Pattern)是 Java 中的一种行为型设计模式,它允许开发者在不修改对象结构的前提下定义新的操作。这种模式将对象结构和操作分离开来,使得操作可以独立地应用于对象结构中的元素。 在访问者...

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

    访问者模式(Visitor)是一种行为设计模式,它允许在不修改对象结构的前提下向对象结构中的元素添加新的操作。这种模式的核心思想是分离了算法和对象结构,使得算法可以在不改变对象结构的情况下独立变化。 访问者...

    设计模式精解-GoF 23种设计模式解析附C++实现源码 完整版

    - 访问者模式:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 每一种设计模式都包含了特定的设计思想和解决策略,对于理解和提高软件设计的质量...

Global site tag (gtag.js) - Google Analytics