• 访问者模式-对象行为型


    定义

    访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

    结构

    访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。

    数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做“双重分派”。节点调用访问者,将它自己传入,访问者则将某算法针对此节点执行。

    访问者模式的示意性类图如下所示:

    访问者模式涉及到的角色如下:

      ●  抽象访问者(Visitor)角色:声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。

      ●  具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。

      ●  抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。

      ●  具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。

      ●  结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如List或Set。

    实现 

    //抽象访问者角色为每一个具体节点都准备了一个访问操作。由于有两个节点,因此,对应就有两个访问操作。
    public interface Visitor {
        /**
         * 对应于NodeA的访问操作
         */
        public void visit(NodeA node);
        /**
         * 对应于NodeB的访问操作
         */
        public void visit(NodeB node);
    }
    //具体访问者VisitorA类
    public class VisitorA implements Visitor {
        /**
         * 对应于NodeA的访问操作
         */
        @Override
        public void visit(NodeA node) {
            System.out.println(node.operationA());
        }
        /**
         * 对应于NodeB的访问操作
         */
        @Override
        public void visit(NodeB node) {
            System.out.println(node.operationB());
        }
    }
    //具体访问者VisitorB类
    public class VisitorB implements Visitor {
        /**
         * 对应于NodeA的访问操作
         */
        @Override
        public void visit(NodeA node) {
            System.out.println(node.operationA());
        }
        /**
         * 对应于NodeB的访问操作
         */
        @Override
        public void visit(NodeB node) {
            System.out.println(node.operationB());
        }
    
    }
    //抽象节点类
    public abstract class Node {
        /**
         * 接受操作
         */
        public abstract void accept(Visitor visitor);
    }
    //具体节点类NodeA
    public class NodeA extends Node{
        /**
         * 接受操作
         */
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
        /**
         * NodeA特有的方法
         */
        public String operationA(){
            return "NodeA";
        }
    
    }
    //具体节点类NodeB
    public class NodeB extends Node{
        /**
         * 接受方法
         */
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
        /**
         * NodeB特有的方法
         */
        public String operationB(){
            return "NodeB";
        }
    }
    //结构对象角色类,这个结构对象角色持有一个聚集,并向外界提供add()方法作为对聚集的管理操作。通过调用这个方法,可以动态地增加一个新的节点。
    public class ObjectStructure {
        
        private List<Node> nodes = new ArrayList<Node>();
        
        /**
         * 执行方法操作
         */
        public void action(Visitor visitor){
            
            for(Node node : nodes)
            {
                node.accept(visitor);
            }
            
        }
        /**
         * 添加一个新元素
         */
        public void add(Node node){
            nodes.add(node);
        }
    }
    //客户端类
    public class Client {
    
        public static void main(String[] args) {
            //创建一个结构对象
            ObjectStructure os = new ObjectStructure();
            //给结构增加一个节点
            os.add(new NodeA());
            //给结构增加一个节点
            os.add(new NodeB());
            //创建一个访问者
            Visitor visitor = new VisitorA();
            os.action(visitor);
        }
    
    }

    在实际系统中访问者模式通常是用来处理复杂的对象树结构的,而且访问者模式可以用来处理跨越多个等级结构的树结构问题。这正是访问者模式的功能强大之处。

    结构对象会遍历它自己所保存的聚集中的所有节点,在本系统中就是节点NodeA和NodeB。首先NodeA会被访问到,这个访问是由以下的操作组成的:

      (1)NodeA对象的接受方法accept()被调用,并将VisitorA对象本身传入;

      (2)NodeA对象反过来调用VisitorA对象的访问方法,并将NodeA对象本身传入;

      (3)VisitorA对象调用NodeA对象的特有方法operationA()。 

    访问者模式的优点

    好的扩展性

    能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。

    好的复用性

    可以通过访问者来定义整个对象结构通用的功能,从而提高复用程度。

    分离无关行为

    可以通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。

    访问者模式的缺点

    对象结构变化很困难

    不适用于对象结构中的类经常变化的情况,因为对象结构发生了改变,访问者的接口和访问者的实现都要发生相应的改变,代价太高。

    破坏封装

    访问者模式通常需要对象结构开放内部数据给访问者和ObjectStructrue,这破坏了对象的封装性。

  • 相关阅读:
    【YBTOJ】【Luogu P4398】[JSOI2008]Blue Mary的战役地图
    【YBTOJ】【Luogu P2601】[ZJOI2009]对称的正方形
    Hystrix超时设置无效及解决原因
    nginx的压缩
    使用nginx配置本地yum 源
    通过nginx制作类似阿里云镜像下载的网站
    nginx下配置显示网站图标
    nginx---自定义日志格式和json日志
    git clone error: RPC failed; result=35, HTTP code = 0 fatal: The remote end hung up unexpectedly
    nginx---缓存
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/5812948.html
Copyright © 2020-2023  润新知