zoukankan      html  css  js  c++  java
  • Visitor模式(访问者设计模式)

    Visitor ?

    • 在Visitor模式中,数据结构与处理被分离开来。我们编写一个表示“访问者”的类来访问数据结构中的元素,
      并把对各元素的处理交给访问者类。这样,当需要增加新的处理时,我们只需要编写新的访问者,然后让
      数据结构可以接受访问者的访问即可。 **

    • 概括: 数据结构与处理彼此分开,当需要实现新数据访问方式的时候,实现Visitor就行了,(缺点:如果增加元素的访问那会非常麻烦)

    理清职责

    • 作用:这里用到Composition设计模式的那个文件和文件夹的例子作为访问者要访问的数据结构。
      地址:https://www.cnblogs.com/dgwblog/p/9840291.html
      名字================>>>> 说明
      | Visitor || 表示访问者的抽象类,它访问文件和文件夹
      |ELement || 表示数据结构的接口,它接受访问者的访问
      |ListVisitor|visitor || 类的子类,显示文件和文件夹一览
      |Fi1e类和Directory || 类的父类,它是抽象类
      |Entry(实现了Element接口)
      |File || 表示文件的类
      |Directory || 表示文件夹的类
      |FileTreatementException || 表示向文件中add时发生的异常的类
      |Main ||测试程序行为的类

    • 简单说明:

      Visitor与ELement 作用在你把代码阅读以后会发现真的是非常简单:如果说Composite中容器与内容一致性,这里是还是将内容一致性维持着,但是将
      那我们需要的数据结构的那部门的实现一套接口访问者提取出来,实现的真正的访问。

    
    rootdir.acctep(new ListVisitor());
    /*ListVisitor visitor = new ListVisitor();
    visitor.visit(rootdir);*/
    
    
    

    accept(接受)方法的调用方式如下。
    element.accept(visitor);
    而visit(访问)方法的调用方式如下。
    visitor.visit (element);
    把上面这两者情况,我们叫做消息的双重分发

    UML

    时序图:

    • 对于Directory类的实例和Fi1e类的实例,我们调用了它们的accept方法
    • 对于每一个Directory类的实例和File类的实例,我们只调用了一次它们的accept方法
    • 对于ListvVisitor的实例,我们调用了它的visit(Directory)和visit(File)方法
    • 处理visit(Directory)和visit(File)的是同一个ListVisitor的实例

    Code

    • Entry :
    public abstract class Entry implements Element {
    
        // 这里实现的Element的目的 是便于在后面的Concreate类中Visitor进行访问
    
        /**
         * 1. 文件名
         * 2. 文件大小
         * @return
         */
        public abstract String getName();
        public abstract int getSize();
    
        /**
         * Directory  增加条目
         * File 不能增加条目
         */
        public Entry add(Entry entry)throws FileTreatementException {
            throw new FileTreatementException();
        }
    
        /**
         * 增加数据的遍历方法itorator
         * @return
         */
        public Iterator iterator() throws FileTreatementException{
            throw new FileTreatementException();
        }
    
        @Override
        public String toString() {
            return getName()+"("+getSize()+")";
        }
    }
    
    
    
    • Element、ListVisitor 、Visitor
    public abstract class Visitor {
    
        /**
         * 作用: 这里的方法的重载数量决定你数据结构中数据的参数
         * 这里我们需要访问 File Directory
         */
        abstract void visit(File file);
    
        abstract void visit(Directory directory);
    
    }
    
    public interface Element {
    
        void acctep(Visitor visitor);
    }
    public class ListVisitor extends Visitor {
    
        private String currentDir="";
    
        @Override
        void visit(File file) {
            System.out.println(currentDir+"/"+file);
        }
    
        /**
         * 实现递归访问结构
         */
        @Override
        void visit(Directory directory) {
            System.out.println(currentDir+"/"+directory);
            String saveDir=currentDir;
            currentDir=currentDir+"/"+directory.getName();
            try {
                Iterator it = directory.iterator();
                while(it.hasNext()){
                    Entry o = (Entry) it.next();
                    o.acctep(this);
                }
                currentDir =saveDir;
            } catch (FileTreatementException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • Directory,File
    public class File extends Entry {
    
        private String name;
    
        private int size;
    
        public File(String name, int size) {
            this.name = name;
            this.size = size;
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        @Override
        public void acctep(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    public class Directory extends Entry {
    
        private String name;
    
        private List<Entry> directory=new ArrayList<>();
    
        public Directory(String name) {
            this.name = name;
        }
    
        @Override
        public Entry add(Entry entry) throws FileTreatementException {
            directory.add(entry);
            return this;
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        /**
         * getSize() | printList(String prefix)
         *
         * 都会递归去遍历下面可能存在的 目录或者文件的子项
         */
    
        @Override
        public int getSize() {
            int size=0;
            Iterator<Entry> it = directory.iterator();
            while (it.hasNext()){
                // 这里的Entry 可能是目录 也可能是文件
                Entry next = it.next();
                size+=next.getSize();
            }
            return size;
        }
    
        @Override
        public Iterator iterator() throws FileTreatementException {
            return directory.iterator();
        }
    
        @Override
        public void acctep(Visitor visitor) {
            visitor.visit(this);
        }
    }
    
    
    
    • FileTreatementException ,
    public class FileTreatementException extends Exception {
    
        public FileTreatementException() {
        }
    
        public FileTreatementException(String message) {
            super(message);
        }
    }
    
    
    
    • MainT
    public class MainT {
    
        public static void main(String[] args) throws FileTreatementException{
            System.out.println("start +++++++++++");
    
            Directory rootdir=new Directory("root");
    
            Directory bindir = new Directory("bin");
            Directory tempdir = new Directory("temp");
            Directory userdir = new Directory("user");
    
            rootdir.add(bindir);
            rootdir.add(tempdir);
            rootdir.add(userdir);
    
            bindir.add(new File("vi",1000));
            bindir.add(new File("notepaid",15000));
    
            rootdir.acctep(new ListVisitor());
            /*ListVisitor visitor = new ListVisitor();
            visitor.visit(rootdir);*/
    
        }
    }
    
    
  • 相关阅读:
    js中剩余参数
    css中 @mixin的使用
    前端Vue中常用rules校验规则
    vue 运行时报错: Cannot assign to read only property 'exports' of object 'Object'
    webpack 常用的loader
    二维码图片合成 ----合成图片以便微信长按保存(移动端)
    VUE中引入第三方JS
    小程序开发者工具--快捷键
    小程序注意事项
    webpack+ES6+less 开发环境搭建
  • 原文地址:https://www.cnblogs.com/dgwblog/p/9862408.html
Copyright © 2011-2022 走看看