笔头云 笔头云
首页
设计模式
SQL教程
Redis
归档
关于
友链

笔头云

非淡泊无以明志,非宁静无以致远。
首页
设计模式
SQL教程
Redis
归档
关于
友链
  • 设计原则
  • 设计模式
  • 单例模式
  • 工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 代理模式
  • 装饰器模式
  • 门面模式
  • 桥接模式
  • 享元模式
  • 组合模式
  • 策略模式
  • 模板方法模式
  • 观察者模式
  • 责任链模式
  • 状态模式
  • 迭代器模式
  • 访问者模式
    • 定义
    • 结构
    • 优点
    • 缺点
    • 应用场景
    • 示例代码
  • 中介模式
  • 命令模式
  • 解释器模式
  • 备忘录模式
  • 设计模式
笔头云
2023-11-03
目录

访问者模式

# 访问者模式

# 定义

访问者模式(Visitor Pattern)是一种行为设计模式,它用于将算法操作从数据结构中分离出来。访问者模式可以在不修改数据结构的情况下,定义新的操作或算法,并将其应用于数据结构中的元素。
访问者模式将数据结构和对数据结构的操作分离开来。数据结构通常由一组不同类型的元素组成,而这些元素可能具有不同的类型和结构。访问者模式通过定义访问者对象,让访问者对象可以独立于数据结构进行操作。访问者对象可以访问并处理数据结构中的每个元素,而不需要在元素类中添加新的操作方法。

访问者模式与策略模式的区别

访问者模式通过访问者对象用于对元素进行不同的操作,而策略模式用于在运行时选择算法或策略。
访问者模式将操作封装在访问者类中,而策略模式将算法封装在策略类中。

# 结构

抽象访问者(Visitor):定义了可以访问和处理每个具体元素的操作方法。它通常定义了多个访问方法,每个方法对应一个具体元素类型。
具体访问者(ConcreteVisitor):实现了抽象访问者定义的操作方法。每个具体访问者对应一个具体的操作或算法。
抽象元素(Element):定义了接受访问者对象访问的接口。它通常包含一个接受访问者的方法,该方法将访问者作为参数传入。
具体元素(ConcreteElement):实现了抽象元素定义的接口。每个具体元素都需要实现接受访问者的方法,并在方法中调用访问者的相应操作方法。
对象结构(Object Structure):包含一组元素对象,并提供让访问者访问元素的方法。对象结构可以是一个集合、列表、树等形式的数据结构。

访问者模式

- img: https://bitouyun.com/images/design-pattern/visitor.png
  link: https://bitouyun.com/images/design-pattern/visitor.png
  name: 访问者模式
1
2
3

# 优点

访问者模式的优点是可以在不修改元素类的情况下,定义新的操作或算法。它将操作和数据结构解耦,使得添加新的操作变得简单,同时也符合开闭原则

# 缺点

增加了新的访问者类,可能会增加系统的复杂性。
为了让访问者对象能够访问元素的内部状态,可能需要在元素类中暴露一些内部细节,破坏了元素类的封装性。

# 应用场景

1.访问者模式通过将操作从数据结构中分离出来,实现了操作和数据结构的解耦。它适用于需要对复杂的数据结构进行访问和操作,并且希望在不修改数据结构的情况下添加新的操作或算法的场景。
2.当一个数据结构包含多种类型的元素,并且每个元素可能需要执行不同的操作时,可以使用访问者模式。这样可以将特定于元素类型的操作封装到访问者对象中,从而使得操作和元素的类型解耦。
3.当需要在不修改元素类的情况下,添加新的操作或算法时,可以使用访问者模式。通过添加新的访问者对象,可以在不影响元素类的情况下,定义新的操作。
4.当需要对数据结构进行多种不相关的操作时,可以使用访问者模式。通过定义不同的访问者对象,可以在不同的上下文中执行不同的操作,而无需修改数据结构。

# 示例代码

场景

使用访问者模式获取普通产品和促销产品信息

    /**
     * 产品访问者
     * 抽象访问者,定义了访问具体元素的方法,每个方法对应一个具体元素类。通过这些方法,访问者可以对元素进行不同的操作。
     */
    public interface ProductVisitor {
    
      // 获取普通商品
      void getNormalProduct(NormalProduct normalProduct);
    
      // 获取促销产品
      void getPromotionProduct(PromotionProduct promotionProduct);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
     * 产品价格计算
     * 具体元素,实现了抽象元素接口,提供了接受访问者的具体实现。
     */
    @Slf4j
    public class ProductPriceCalculator implements ProductVisitor {
    
      @Override
      public void getNormalProduct(NormalProduct normalProduct) {
        log.info("商品:{},价格:{}", normalProduct.getName(), normalProduct.getPrice());
      }
    
      @Override
      public void getPromotionProduct(PromotionProduct promotionProduct) {
        log.info("商品:{},价格:{},折扣:{}", promotionProduct.getName(), promotionProduct.getPrice(), promotionProduct.getDiscountRate());
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
     * 产品抽象元素
     * 抽象元素,定义一个接受访问者对象的接口,通常会有一个接受(accept)方法,接受访问者方法。
     */
    public interface ProductElement {
      // 接受访问者方法
      void accept(ProductVisitor productVisitor);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    /**
     * 普通商品具体元素类
     * 具体元素,实现了抽象元素接口,提供了接受访问者的具体实现。
     */
    @AllArgsConstructor
    public class NormalProduct implements ProductElement {
    
      private String name;
      private double price;
    
      public String getName() {
        return name;
      }
    
      public double getPrice() {
        return price;
      }
    
      @Override
      public void accept(ProductVisitor productVisitor) {
        productVisitor.getNormalProduct(this);
      }
    }
    
    /**
     * 促销产品具体元素类
     * 具体元素,实现了抽象元素接口,提供了接受访问者的具体实现。
     */
    @AllArgsConstructor
    public class PromotionProduct implements ProductElement {
      private String name;
      private double price;
      private double discountRate;
    
      public String getName() {
        return name;
      }
    
      public double getPrice() {
        return price;
      }
    
      public double getDiscountRate() {
        return discountRate;
      }
    
      @Override
      public void accept(ProductVisitor productVisitor) {
        productVisitor.getPromotionProduct(this);
      }
    }
    
    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
    49
    50
    51
    /**
     * 产品结构类
     * 对象结构,包含一组元素对象,并提供让访问者访问元素的方法。
     */
    public class ProductStructure {
      private List<ProductElement> elements = new ArrayList<>();
    
      // 添加元素
      public void add(ProductElement productElement) {
        elements.add(productElement);
      }
    
      // 移除元素
      public void remove(ProductElement productElement) {
        elements.remove(productElement);
      }
    
      // 接受访问者
      public void accept(ProductVisitor productVisitor) {
        for (ProductElement productElement : elements) {
          productElement.accept(productVisitor);
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /**
     * 测试类
     */
    public class Client {
    
      public static void main(String[] args) {
        // 1.对象结构测试
        objectStructureTest();
        // 2.无对象结构测试
        test();
      }
    
      private static void objectStructureTest() {
        // 对象结构
        ProductStructure objectStructure = new ProductStructure();
        objectStructure.add(new NormalProduct("普通产品", 199));
        objectStructure.add(new PromotionProduct("促销产品", 99, 0.5));
        // 访问者
        ProductVisitor visitor = new ProductPriceCalculator();
        objectStructure.accept(visitor);
      }
    
      private static void test() {
        List<ProductElement> products = Arrays.asList(new NormalProduct("普通产品", 199),
                new PromotionProduct("促销产品", 99, 0.5));
        ProductVisitor visitor = new ProductPriceCalculator();
        for (ProductElement product : products) {
          product.accept(visitor);
        }
      }
    }
    
    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
    // Make sure to add code blocks to your code group
    #行为型模式#设计模式
    上次更新: 2023/11/17, 09:38:49
    迭代器模式
    中介模式

    ← 迭代器模式 中介模式→

    最近更新
    01
    FRP内网穿透docker部署 工具
    05-07
    02
    Office Util办公工具 工具
    01-14
    03
    Git常用命令
    01-16
    更多文章>
    Theme by Vdoing | Copyright © 2023-2025 鲁ICP备2023014898号 公安备案号:37020302372159
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×