• 设计模式学习(十九):访问者模式


    设计模式学习(十九):访问者模式

    作者:Grey

    原文地址:

    博客园:设计模式学习(十九):访问者模式

    CSDN:设计模式学习(十九):访问者模式

    访问者模式

    访问者模式是一种行为型模式。

    访问者模式在结构不变的情况下动态改变对于内部元素的动作。

    举例说明:

    假设我们需要构造一台电脑,有主板( Board ),CPU ,内存( Memory ),但是针对企业用户和个人用户,电脑组件的价格是不一样的,我们需要根据不同客户获取一台电脑的总价格。

    我们先抽象出电脑组件这个类

    public abstract class ComputerPart {
        abstract void accept(Visitor visitor);
    
        abstract int getPrice();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    每个具体组件会继承这个抽象类,以主板( Board )为例

    public class Board extends ComputerPart {
        @Override
        void accept(Visitor visitor) {
            visitor.visitBoard(this);
        }
    
        @Override
        int getPrice() {
            return 20;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    抽象出一个访问者( Visitor )接口,

    public interface Visitor {
        void visitCPU(CPU cpu);
    
        void visitBoard(Board board);
    
        void visitMemory(Memory memory);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    每个具体类型的访问者实现这个接口,然后定义其不同的价格策略,以公司访问者为例( CorpVisitor )

    public class CorpVisitor implements Visitor {
        private int totalPrice;
    
        @Override
        public void visitCPU(CPU cpu) {
            totalPrice += cpu.getPrice() - 1;
        }
    
        @Override
        public void visitBoard(Board board) {
            totalPrice += board.getPrice() - 2;
        }
    
        @Override
        public void visitMemory(Memory memory) {
            totalPrice += memory.getPrice() - 3;
        }
    
        public int getTotalPrice() {
            return totalPrice;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    个人访问者( PersonalVisitor )类似

    
    public class PersonalVisitor implements Visitor {
        private int totalPrice;
    
        @Override
        public void visitCPU(CPU cpu) {
            totalPrice += cpu.getPrice() + 1;
        }
    
        @Override
        public void visitBoard(Board board) {
            totalPrice += board.getPrice() + 2;
        }
    
        @Override
        public void visitMemory(Memory memory) {
            totalPrice += memory.getPrice() + 3;
        }
    
    
        public int getTotalPrice() {
            return totalPrice;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    主方法调用方式如下

    public class Main {
        public static void main(String[] args) {
            ComputerPart cpu = new CPU();
            ComputerPart memory = new Memory();
            ComputerPart board = new Board();
            PersonalVisitor personalVisitor = new PersonalVisitor();
            cpu.accept(personalVisitor);
            memory.accept(personalVisitor);
            board.accept(personalVisitor);
            System.out.println(personalVisitor.getTotalPrice());
    
            ComputerPart cpu2 = new CPU();
            ComputerPart memory2 = new Memory();
            ComputerPart board2 = new Board();
            CorpVisitor corpVisitor = new CorpVisitor();
            cpu2.accept(corpVisitor);
            memory2.accept(corpVisitor);
            board2.accept(corpVisitor);
            System.out.println(corpVisitor.getTotalPrice());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    可以看到,不同的访问者,对于电脑的价格是不一样的。

    上述示例的 UML 图如下

    img

    访问者模式的应用

    Java SE 中的 FileVisitor 使用了访问者模式,使用示例

    import java.io.IOException;
    import java.nio.file.FileVisitResult;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.attribute.BasicFileAttributes;
    
    /**
     * @author GreyZeng
     * @version 1.0, 2022/8/11
     */
    public class FileVisitorTest {
        public static void main(String[] args) throws IOException {
            // 使用FileVisitor对目录进行遍历
            // 访问当前目录的所有文件
            Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
    
                // 在访问子目录前触发该方法
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    System.out.println("正在访问" + dir + "目录");
                    return FileVisitResult.CONTINUE;
                }
    
                // 在访问文件时触发该方法
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println("正在访问" + file + "文件");
                    return FileVisitResult.CONTINUE;
                }
    
                // 在访问失败时触发该方法
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    // 写一些具体的业务逻辑
                    return super.visitFileFailed(file, exc);
                }
    
                // 在访问目录之后触发该方法
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 写一些具体的业务逻辑
                    return super.postVisitDirectory(dir, exc);
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    其他应用

    • 做编译器的时候,需要生成 AST ,进行类型检查 根据抽象语法树,生成中间代码;

    • XML 文件解析;

    • Spring 中的 BeanDefinitionVisitor

    UML 和 代码

    UML 图

    代码

    更多

    设计模式学习专栏

    参考资料

  • 相关阅读:
    VLAN通讯
    RabbitMQ入门与进阶实战
    【论文翻译】S4: a High-sparsity, High-performance AI Accelerator
    基于java_ssm_vue鲜花在线销售商城网站-计算机毕业设计
    iso27001信息安全体系认证咨询
    【医学分割】Medical Image Segmentation Using Deep Learning: A Survey
    问题:vue2+elementui,tabs切换显示表格并设置表格选中行高亮失败
    一键自动化博客发布工具,用过的人都说好(51cto篇)
    react+ts手写cron表达式转换组件
    交换机端口灯常亮 端口up状态 服务器设置ip交换机获取不到服务器网卡mac地址 不能通信
  • 原文地址:https://blog.csdn.net/hotonyhui/article/details/127821517