java访问者模式

访问者模式

访问者模式是一种行为型设计模式,它允许你将对象操作(算法)与对象结构分离。可以在不更改对象的类的情况下,向现有对象结构添加新操作。

应用场景

访问者模式适用于以下场景:

  • 当你需要在一些类群中定义新的操作,但不希望代码频繁更改这些类群时,可以使用访问者模式。
  • 如果您需要对已有对象结构进行复杂的结构化操作,可能需要该模式。
  • 该模式可以帮助在不改变对象结构的情况下向该结构中添加新功能。

结构

访问者模式包括以下组件:

  • Visitor: 表示访问者的抽象类或接口。需要为对象结构中每个类群实现访问者操作。
  • ConcreteVisitor: 具体的访问者实现,实现 Visitor 接口并在每个类群中提供具体操作。
  • Element: 所有对象结构的基类,必须有一个 Accept 方法。该方法需要将访问者作为参数,以便处理程序可以在 Visitor 调用期间调用 Element 特定的操作。
  • ConcreteElement: 表示具体元素的类。它们必须实现 Accept 并将自身作为参数传递给访问者,以便访问者可以遍历元素并调用特定于该元素类型的操作。
  • ObjectStructure: 表示对象结构的类。它需要有一个数据结构来存储元素,并能够将访问者传递给所有元素,以便访问者可以遍历整个对象结构。

代码示例

下面是一个使用访问者模式来计算购物车中商品价格的示例。假设我们购物车中有书籍和电影两种商品,我们需要计算它们的价格并返回结果。

首先,我们需要定义访问者接口

public interface Visitor {
    double visit(Book book);
    double visit(Movie movie);
}

然后,我们需要定义商品基类 Element 和具体商品子类

public interface Element {
    double accept(Visitor visitor);
}

public class Book implements Element {

    private String name;
    private double price;
    private double weight;

    public Book(String name, double price, double weight) {
        this.name = name;
        this.price = price;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public double getWeight() {
        return weight;
    }

    @Override
    public double accept(Visitor visitor) {
        return visitor.visit(this);
    }
}

public class Movie implements Element {

    private String name;
    private double price;
    private int length;

    public Movie(String name, double price, int length) {
        this.name = name;
        this.price = price;
        this.length = length;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getLength() {
        return length;
    }

    @Override
    public double accept(Visitor visitor) {
        return visitor.visit(this);
    }
}

现在我们需要实现具体的访问者类 ConcreteVisitor

public class PriceVisitor implements Visitor {

    @Override
    public double visit(Book book) {
        return book.getPrice();
    }

    @Override
    public double visit(Movie movie) {
        return movie.getPrice() * movie.getLength() / 60.0;
    }
}

最后,我们需要定义 ObjectStructure

public class ShoppingCart {

    private List<Element> elements;

    public ShoppingCart() {
        elements = new ArrayList<>();
    }

    public void addElement(Element element) {
        elements.add(element);
    }

    public void removeElement(Element element) {
        elements.remove(element);
    }

    public double calculateTotalPrice(Visitor visitor) {
        double totalPrice = 0.0;
        for (Element element : elements) {
            totalPrice += element.accept(visitor);
        }
        return totalPrice;
    }
}

现在我们可以使用访问者模式来计算购物车中商品价格:

public static void main(String[] args) {
    ShoppingCart shoppingCart = new ShoppingCart();
    shoppingCart.addElement(new Book("Design Patterns", 40.0, 1.5));
    shoppingCart.addElement(new Movie("The Lord of the Rings", 20.0, 180));
    shoppingCart.addElement(new Book("Effective Java", 50.0, 1.0));
    shoppingCart.addElement(new Movie("Inception", 15.0, 120));

    Visitor visitor = new PriceVisitor();
    double totalPrice = shoppingCart.calculateTotalPrice(visitor);
    System.out.println("Total Price: $" + totalPrice);
}

输出结果:

Total Price: $110.0

优缺点

优点:

  • 可以对已有对象结构进行复杂的结构化操作,而无需修改这些对象结构。
  • 可以使用具体访问者来添加新的操作,而不必更改现有代码。
  • 可以将相关操作代码集中到一起,而不是分散在整个程序中。
  • 可以简化算法代码,使其易于扩展和维护。
  • 可以让客户端代码和元素类保持相对不变。

缺点:

  • 如果元素类层次结构经常更改,则访问者模式可能会变得很麻烦。
  • 在使用访问者模式时添加新元素可能比添加新操作更困难。
  • 访问者模式可能会导致对象结构中的许多小的类。
  • 具体的访问者可能需要访问元素的私有成员,这可能会破坏元素的封装。

总结

访问者模式强调了“单一职责原则”和“开放/封闭原则”,它提供了一种方便的方式来添加新操作,而无需更改现有代码。它适用于对象结构相对稳定的场景,并且可用于执行诸如优化、验证、反向操作等任务。它不应被滥用,因为在某些情况下,它可能会增加系统的复杂性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值