掌握设计模式--访问者模式

访问者模式(Visitor Pattern)

访问者模式(Visitor Pattern)是一种行为设计模式,它允许你将操作(方法)封装到另一个类中,使得你可以在不修改现有类的情况下,向其添加新的操作。

核心思想 是将数据结构和对数据的操作分离通过访问者对象来对数据进行操作,而不是将操作方法直接嵌入数据结构本身。

组成部分

  1. Visitor(访问者):这是一个接口或抽象类,定义了针对各个元素类(通常是数据结构中的元素)的操作方法。

  2. ConcreteVisitor(具体访问者):实现访问者接口的具体类,定义了具体的操作。

  3. Element(元素):这是一个接口或抽象类,定义了接受访问者的接口。通常是数据结构的元素。

  4. ConcreteElement(具体元素):实现元素接口的具体类,定义数据结构的具体元素。

  5. ObjectStructure(对象结构):维护一个元素集合,通常是一个集合或树形结构,可以接受访问者的访问。

案例代码

假设我们有一个简单的元素结构,表示不同类型的账单项目,我们要为每种账单项目添加不同的计算方式,比如食物和服装账单,分别使用不同的折扣,这个折扣会经常发生变化。可以通过访问者模式来解决这个问题。

案例类图

账单--元素接口

java 复制代码
public interface BillItem {
    void accept(BillVisitor visitor);
}

账单--具体元素类:食物类和服装类

java 复制代码
public class FoodItem implements BillItem {
    private double price;

    public FoodItem(double price) {
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public void accept(BillVisitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素:ClothingItem
class ClothingItem implements BillItem {
    private double price;

    public ClothingItem(double price) {
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public void accept(BillVisitor visitor) {
        visitor.visit(this);
    }
}

账单--访问者接口

java 复制代码
public interface BillVisitor {
    void visit(FoodItem foodItem);
    void visit(ClothingItem clothingItem);
}

账单--具体访问者

java 复制代码
public class DiscountVisitor implements BillVisitor {
    @Override
    public void visit(FoodItem foodItem) {
        // 9折
        double discountedPrice = foodItem.getPrice() * 0.9;
        System.out.println("食品折扣价格: " + discountedPrice);
    }

    @Override
    public void visit(ClothingItem clothingItem) {
        // 8折
        double discountedPrice = clothingItem.getPrice() * 0.8;
        System.out.println("服装项目的折扣价格: " + discountedPrice);
    }
}

测试客户端

java 复制代码
public class VisitorPatternExample {
    public static void main(String[] args) {
        BillItem food = new FoodItem(100.0);
        BillItem clothing = new ClothingItem(200.0);

        BillVisitor discountVisitor = new DiscountVisitor();

        food.accept(discountVisitor);
        clothing.accept(discountVisitor);
    }
}

测试输出结果

食品折扣价格: 90.0

服装项目的折扣价格: 160.0

解释

  1. BillVisitor 是访问者接口,它定义了针对不同类型账单项目(如 FoodItemClothingItem)的操作方法。
  2. BillItem 是元素接口,所有账单项目类都实现该接口。
  3. FoodItemClothingItem 是具体的元素类,它们实现了 BillItem 接口,并在 accept 方法中调用访问者的相应操作。
  4. DiscountVisitor 是一个具体的访问者,计算并打印带折扣的价格。

当需要为账单项目添加新的操作时,只需要添加一个新的访问者类,而不必修改现有的 FoodItemClothingItem 类。这样就实现了操作和数据结构的分离。

优缺点和适用场景

优点

  • 扩展性好:可以方便地添加新的操作而不修改现有元素类(数据结构)。
  • 将数据结构和操作解耦:操作逻辑集中在访问者类中,数据结构集中在元素类中。
  • 符合开闭原则:可以在不修改原有代码的基础上,增加新的功能。

缺点

  • 元素类难以修改:如果元素类的结构改变,需要修改所有访问者类,这在某些情况下会变得麻烦。
  • 不适合频繁变动的数据结构:访问者模式适用于元素类结构较为稳定的情况,如果元素类需要频繁变化,访问者模式可能导致很多不必要的修改。

适用场景

  • 元素类结构稳定,但你需要在不修改这些类的情况下,增加新的操作。
  • 需要对一个对象结构中的元素进行不同的操作时,访问者模式可以避免在元素类中写入大量的业务逻辑。

访问者模式是当你有一个固定的元素结构,但需要频繁进行不同的操作时非常有用的设计模式。

总结

访问者模式是一种行为设计模式,其核心在于通过将操作逻辑封装到访问者对象中,使得在不修改对象结构的前提下,能够为一组对象添加新的行为,同时将数据结构行为操作解耦,适用于复杂对象结构中操作变化频繁的场景。

需要查看往期设计模式文章的,可以在个人主页中或者文章开头的集合中查看,可关注我,持续更新中。。。


超实用的SpringAOP实战之日志记录

2023年下半年软考考试重磅消息

通过软考后却领取不到实体证书?

计算机算法设计与分析(第5版)

Java全栈学习路线、学习资源和面试题一条龙

软考证书=职称证书?

软考中级--软件设计师毫无保留的备考分享

相关推荐
佚明zj18 分钟前
【设计模式】抽象工厂模式(含与工厂方法模式的对比)
设计模式·工厂方法模式·抽象工厂模式
患得患失94919 分钟前
【设计模式】策略模式(Strategy Pattern)详解
设计模式·bash·策略模式
字节架构前端4 小时前
从顶层视角解读技术架构设计:实用指南与最佳实践
前端·设计模式·架构
高飞的Leo5 小时前
适配器模式及其典型应用
设计模式
Hanson Huang9 小时前
23种设计模式-状态(State)设计模式
java·设计模式·状态模式·行为型设计模式
Hanson Huang20 小时前
23中设计模式-迭代器(Iterator)设计模式
java·设计模式·迭代器模式·行为型设计模式
系统工程实验室21 小时前
设计模式之外观模式
设计模式·外观模式
Exploring1 天前
【笔记】设计模式总结
设计模式
Antonio9151 天前
【设计模式】外观模式
设计模式
Hanson Huang1 天前
23种设计模式-原型(Prototype)设计模式
设计模式·原型模式