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

基础结构
// 元素接口
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
使用场景与优缺点
适用场景:
- 对象结构比较稳定,但需要经常增加新的操作
- 需要对一个对象结构中的对象进行很多不同的且不相关的操作
- 需要避免在元素类中暴露内部状态
优点:
- 符合单一职责原则,相关操作集中在访问者中
- 扩展性好,添加新操作只需添加新访问者
- 可以在不修改元素类的情况下添加新操作
缺点:
- 增加新元素困难,需要修改访问者接口
- 破坏了封装,访问者需要知道元素内部细节
- 当元素类变化频繁时不适合使用
这个案例展示了访问者模式如何优雅地分离数据结构和操作,使得添加新的操作变得简单方便。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播