设计模式Java实现-访问者模式
✨这里是第七人格的博客✨小七,欢迎您的到来~✨
🍅系列专栏:设计模式🍅
✈️本篇内容: 访问者模式✈️
🍱 本篇收录完整代码地址:gitee.com/diqirenge/d… 🍱
楔子
有时候小七在想,技术真的有那么重要吗?
举个例子,如果不走内推,以小七现在的年龄和学历,毫不夸张的说,根本不会有面试的机会,简历直接就过不了。但是转而一想,也正是自己不断的自我提升,才会换来朋友们的信任与内推,所以一定要学会投资自己。
需求背景
假设我们有一个电子商务系统,其中包含了不同类型的商品,如书籍、电子产品等。每种商品都有一些共同属性和特有属性。现在,我们需要对不同类型的商品进行不同的操作,比如打印商品信息、计算商品的价格等。
分析设计
为了实现这些功能,我们可以考虑使用访问者模式,因为它允许我们在不修改商品类的情况下增加新的操作。
UML图
根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码
模块名称
visitor
模块地址
模块描述
访问者模式代码示例
代码实现
1、定义商品接口
/**
* 商品接口,定义了接受访问者的方法
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
interface Product {
/**
* 接受一个访问者对象,以便访问者可以操作该商品
* @param visitor
*/
void accept(ProductVisitor visitor);
}
2、定义访问者接口
/**
* 访问者接口,定义了访问不同类型商品的方法
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
interface ProductVisitor {
/**
* 访问书籍的方法
* @param book
*/
void visitBook(Book book);
/**
* 访问电子产品的方法
* @param device
*/
void visitElectronicDevice(ElectronicDevice device);
}
3、实现书籍类
/**
* 书籍类,实现了Product接口
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
public class Book implements Product {
/**
* 书籍的标题
*/
private String title;
/**
* 书籍的作者
*/
private String author;
/**
* 书籍的价格
*/
private double price;
/**
* 书籍的构造函数,用于初始化书籍的信息
* @param title
* @param author
* @param price
*/
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
}
/**
* 实现Product接口的accept方法,用于接受访问者
* @param visitor
*/
@Override
public void accept(ProductVisitor visitor) {
// 调用访问者的visitBook方法,传入当前书籍对象
visitor.visitBook(this);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
4、实现电子产品类
/**
* 电子产品类,实现了Product接口
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
class ElectronicDevice implements Product {
/**
* 电子产品的型号
*/
private String model;
/**
* 电子产品的品牌
*/
private String brand;
/**
* 电子产品的价格
*/
private double price;
/**
* 电子产品的构造函数,用于初始化电子产品的信息
* @param model
* @param brand
* @param price
*/
public ElectronicDevice(String model, String brand, double price) {
this.model = model;
this.brand = brand;
this.price = price;
}
/**
* 实现Product接口的accept方法,用于接受访问者
* @param visitor
*/
@Override
public void accept(ProductVisitor visitor) {
// 调用访问者的visitElectronicDevice方法,传入当前电子产品对象
visitor.visitElectronicDevice(this);
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
5、实现计算价格行为的访问者
/**
* 计算价格访问者类,实现了ProductVisitor接口
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
class CalculatePriceVisitor implements ProductVisitor {
private double totalPrice = 0; // 用于累计总价格
// 实现访问书籍的方法,累加书籍的价格到总价格中
@Override
public void visitBook(Book book) {
totalPrice += book.getPrice();
}
// 实现访问电子产品的方法,累加电子产品的价格到总价格中
@Override
public void visitElectronicDevice(ElectronicDevice device) {
totalPrice += device.getPrice();
}
// 获取总价格的方法
public double getTotalPrice() {
return totalPrice;
}
}
6、实现打印信息行为的访问者
/**
* 打印信息访问者类,实现了ProductVisitor接口
* 关注公众号【奔跑的码畜】,一起进步不迷路
*
* @author 第七人格
* @date 2024/06/25
*/
class PrintInfoVisitor implements ProductVisitor {
/**
* 实现访问书籍的方法,打印书籍信息
* @param book
*/
@Override
public void visitBook(Book book) {
System.out.println("书籍信息: 标题=" + book.getTitle() + ", 作者=" + book.getAuthor() + ", 价格=" + book.getPrice());
}
/**
* 实现访问电子产品的方法,打印电子产品信息
* @param device
*/
@Override
public void visitElectronicDevice(ElectronicDevice device) {
System.out.println("电子产品信息: 型号=" + device.getModel() + ", 品牌=" + device.getBrand() + ", 价格=" + device.getPrice());
}
}
7、编写测试类
8、测试结果
书籍信息: 标题=设计模式, 作者=第七人格, 价格=7.0
电子产品信息: 型号=HUAWEI Pura 70, 品牌=华为, 价格=6999.0
总价格: 7006.0
实现要点
-
Visitor(访问者):接口或抽象类,定义了对每一个元素类(Element)的访问操作。
ProductVisitor接口充当Visitor角色,它声明了访问不同产品类型的方法。
-
ConcreteVisitor(具体访问者):实现了Visitor接口的类,它实现了对每个元素类的具体操作。
PrintInfoVisitor和CalculatePriceVisitor类实现了这个接口,分别用于打印产品信息和计算产品价格。
-
Element(元素):接口或抽象类,定义了一个接受访问者(Accept)的方法。
对应代码示例中的Product接口。
-
ConcreteElement(具体元素):实现了Element接口的类,它们通常包含一些状态信息,这些信息在访问时被传递给访问者。
对应代码示例中的Book和ElectronicDevice类。
-
ObjectStructure(对象结构):可以遍历元素集合,并负责提供访问者访问元素的方法。
代码实例中没有这个对象结构,它持有产品的集合,并可以遍历这些产品,让访问者访问它们。我们可以提供这个方法给购物车。
总结
访问者模式允许我们在不改变数据结构的情况下增加新的操作。在我们的电子商务系统例子中,通过定义ProductVisitor接口和具体的访问者类,我们能够轻松地添加新的操作,如打印信息或计算价格,而无需修改现有的产品类。这提供了很大的灵活性,尤其是在需要频繁添加新功能或操作时。
转载自:https://juejin.cn/post/7383894687302303753