Java案例如何实现访问者模式?

wen java案例 36

Java访问者模式实现案例

访问者模式(Visitor Pattern)是一种将数据结构与数据操作分离的设计模式,以下是一个完整的实现案例:

Java案例如何实现访问者模式?

基础结构

// 元素接口
interface Element {
    void accept(Visitor visitor);
}
// 具体元素类 - 书
class Book implements Element {
    private String name;
    private double price;
    public Book(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() { return name; }
    public double getPrice() { return price; }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素类 - 电子产品
class Electronic implements Element {
    private String name;
    private double price;
    public Electronic(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() { return name; }
    public double getPrice() { return price; }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
// 访问者接口
interface Visitor {
    void visit(Book book);
    void visit(Electronic electronic);
}
// 具体访问者 - 计算总价
class PriceCalculator implements Visitor {
    private double totalPrice = 0;
    @Override
    public void visit(Book book) {
        totalPrice += book.getPrice();
    }
    @Override
    public void visit(Electronic electronic) {
        // 电子产品加税
        totalPrice += electronic.getPrice() * 1.1;
    }
    public double getTotalPrice() {
        return totalPrice;
    }
}
// 具体访问者 - 打折处理
class DiscountVisitor implements Visitor {
    @Override
    public void visit(Book book) {
        System.out.println("书籍【" + book.getName() + "】打8折,原价:" 
                         + book.getPrice() + ",现价:" + book.getPrice() * 0.8);
    }
    @Override
    public void visit(Electronic electronic) {
        System.out.println("电子产品【" + electronic.getName() + "】打9折,原价:" 
                         + electronic.getPrice() + ",现价:" + electronic.getPrice() * 0.9);
    }
}

对象结构类

import java.util.ArrayList;
import java.util.List;
class ShoppingCart {
    private List<Element> items = new ArrayList<>();
    public void addItem(Element item) {
        items.add(item);
    }
    public void removeItem(Element item) {
        items.remove(item);
    }
    public void accept(Visitor visitor) {
        for (Element item : items) {
            item.accept(visitor);
        }
    }
}

客户使用示例

public class VisitorPatternDemo {
    public static void main(String[] args) {
        // 创建购物车
        ShoppingCart cart = new ShoppingCart();
        // 添加商品
        cart.addItem(new Book("设计模式", 68.0));
        cart.addItem(new Book("Java编程思想", 99.0));
        cart.addItem(new Electronic("笔记本电脑", 5000.0));
        cart.addItem(new Electronic("手机", 3000.0));
        // 使用价格计算器访问者
        System.out.println("=== 计算总价 ===");
        PriceCalculator priceCalculator = new PriceCalculator();
        cart.accept(priceCalculator);
        System.out.println("总价: " + priceCalculator.getTotalPrice());
        // 使用打折访问者
        System.out.println("\n=== 打折处理 ===");
        DiscountVisitor discountVisitor = new DiscountVisitor();
        cart.accept(discountVisitor);
    }
}

运行结果

=== 计算总价 ===
总价: 8967.0
=== 打折处理 ===
书籍【设计模式】打8折,原价:68.0,现价:54.4
书籍【Java编程思想】打9折,原价:99.0,现价:79.2
电子产品【笔记本电脑】打9折,原价:5000.0,现价:4500.0
电子产品【手机】打9折,原价:3000.0,现价:2700.0

使用场景与优缺点

适用场景:

  • 对象结构比较稳定,但需要经常增加新的操作
  • 需要对一个对象结构中的对象进行很多不同的且不相关的操作
  • 需要避免在元素类中暴露内部状态

优点:

  • 符合单一职责原则,相关操作集中在访问者中
  • 扩展性好,添加新操作只需添加新访问者
  • 可以在不修改元素类的情况下添加新操作

缺点:

  • 增加新元素困难,需要修改访问者接口
  • 破坏了封装,访问者需要知道元素内部细节
  • 当元素类变化频繁时不适合使用

这个案例展示了访问者模式如何优雅地分离数据结构和操作,使得添加新的操作变得简单方便。

抱歉,评论功能暂时关闭!