首页 > 其他分享 >设计模式学习(十九):访问者模式

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

时间:2022-11-12 16:12:00浏览次数:67  
标签:void file Override 设计模式 十九 public 访问者

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

作者:Grey

原文地址:

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

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

访问者模式

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

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

举例说明:

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

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

public abstract class ComputerPart {
    abstract void accept(Visitor visitor);

    abstract int getPrice();
}

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

public class Board extends ComputerPart {
    @Override
    void accept(Visitor visitor) {
        visitor.visitBoard(this);
    }

    @Override
    int getPrice() {
        return 20;
    }
}

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

public interface Visitor {
    void visitCPU(CPU cpu);

    void visitBoard(Board board);

    void visitMemory(Memory memory);
}

每个具体类型的访问者实现这个接口,然后定义其不同的价格策略,以公司访问者为例( 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;
    }
}

个人访问者( 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;
    }
}

主方法调用方式如下

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());
    }
}

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

上述示例的 UML 图如下

image

访问者模式的应用

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 <a href="mailto:[email protected]">GreyZeng</a>
 * @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);
            }
        });
    }
}

其他应用

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

  • XML 文件解析;

  • Spring 中的 BeanDefinitionVisitor

UML 和 代码

UML 图

代码

更多

设计模式学习专栏

参考资料

标签:void,file,Override,设计模式,十九,public,访问者
From: https://www.cnblogs.com/greyzeng/p/16883994.html

相关文章

  • 设计模式学习(十八):迭代器模式
    设计模式学习(十八):迭代器模式作者:Grey原文地址:博客园:设计模式学习(十八):迭代器模式CSDN:设计模式学习(十八):迭代器模式迭代器模式迭代器模式是一种行为型模式。迭代器最典......
  • 设计模式学习(十七):状态模式
    设计模式学习(十七):状态模式作者:Grey原文地址:博客园:设计模式学习(十七):状态模式CSDN:设计模式学习(十七):状态模式状态模式状态模式是一种行为型模式。对象的行为依赖于它的......
  • 设计模式学习(十六):责任链模式
    设计模式学习(十六):责任链模式作者:Grey原文地址:博客园:设计模式学习(十六):责任链模式CSDN:设计模式学习(十六):责任链模式责任链模式责任链模式是一种行为型模式。举例说明:有......
  • 设计模式学习(十五):策略模式
    设计模式学习(十五):策略模式作者:Grey原文地址:博客园:设计模式学习(十五):策略模式CSDN:设计模式学习(十五):策略模式策略模式策略模式是一种行为型模式,它定义了一组算法,将每个......
  • 设计模式-建造者模式
    在我们生活中的对象比如汽车,它是由车轮、车架、发动机等组合起来的对象,但是往往使用的人只想要一辆汽车并不想知道创建汽车的过程此时就可以使用建造者模式。在软件开发中,也......
  • 设计模式学习(十四):模板方法
    设计模式学习(十四):模板方法作者:Grey原文地址:博客园:设计模式学习(十四):模板方法CSDN:设计模式学习(十四):模板方法模板方法模板方法是一种行为型模式。假设我们要实现一个游......
  • 访问者模式
    访问者模式有点小复杂,而且需要在实际的时候提前留好后门,下面通过简单的例子来介绍一下。场景就是邮件发送,通知客户怎么了怎么了,后面可能需要短信或者app也推。推之前或推送......
  • Java静态代理设计模式模式(多线程Runnable)
    静态代理设计模式,就是代理对象来帮你忙前忙后,你负责出席一下就好了。需要:1.实现相同的接口2.真实角色3.代理角色,里面有一个成员是接口对象(实际上是真实角色----接口实......
  • 设计模式学习(十三):观察者模式
    设计模式学习(十三):观察者模式作者:Grey原文地址:博客园:设计模式学习(十三):观察者模式CSDN:设计模式学习(十三):观察者模式观察者模式观察者模式是一种行为型模式。在对象之间......
  • C#设计模式之建造者模式
      原文网址:https://www.jb51.net/article/254976.htm场景:我们的冒险家,现在需要去武器商店买一把兵器,有刀和剑两种武器,冒险者可以告诉武器商人需要哪一种武器,然后武器商......