Java设计模式 - 访问者模式
😄 不断学习才是王道
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!
简介
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
———— 菜鸟联盟
访问者模式解析
访问者模式主要是将数据操作和数据结构分离开来,解决他们的耦合性问题。就是在访问类里面添加对外提供接待访问者的接口。
浅浅的理解,实际上就是有个元素接口类,里面包含未实现的方法,并且需要将访问者接口类对象带进去;在具体扩展的实体类中实现了元素接口类的方法,也就是调用了访问者对象的方法,这就相当于真正实现的方法都是由访问者接口类的子类去实现,这就形成了元素实体的可扩展,访问者的可扩展,并且他们都互不影响。
原理UML如图:
角色与职责
- Visitor 访问者,为对象ConcreteElement类声明了visit方法。
ConcreteVisitor 具体访问者,实现Visitor的每一个方法。
- ObjectStruture 能够枚举其他元素,用来允许访问者访问元素。
- Element 接收访问者对象。
- ConcreteElement 具体元素
访问者模式实例
采用汽车的例子来理解访问者模式,定义元素接口,将访问者接口对象带入,在具体的元素类中,通过访问者去调用相应方法。则访问者接口定义了元素所需的方法,由具体的访问者类去实现,数据结构是用来对元素进行管理,管理访问者能否访问元素。
类图:
代码如下:
①、定义访问者接口
定义元素各自所需的方法,这里定义vidit方法,通过参数来区分。
package com.lyd.demo.visitor;
import com.lyd.demo.element.car.Benz;
import com.lyd.demo.element.car.HongQi;
/**
* @Author: lyd
* @Description: 访问者接口
* @Date: 2022-09-04
*/
public interface ICarPartVisitor {
public void visit(Benz benz);
public void visit(HongQi hongQi);
}
②、定义具体访问者
编写所有具体元素的业务
package com.lyd.demo.visitor;
import com.lyd.demo.element.car.Benz;
import com.lyd.demo.element.car.HongQi;
/**
* @Author: lyd
* @Description: 具体访问者方法
* @Date: 2022-09-04
*/
public class CarDisplayVisitor implements ICarPartVisitor {
@Override
public void visit(Benz benz) {
System.out.println(" 奔驰旗舰店汽车 ");
}
@Override
public void visit(HongQi hongQi) {
System.out.println(" 红旗旗舰店汽车 ");
}
}
③、定义元素实体接口
带入访问者接口类对象,由具体的元素去实现,通过访问者调用方法。
package com.lyd.demo.element;
import com.lyd.demo.visitor.ICarPartVisitor;
/**
* @Author: lyd
* @Description: 元素实体接口类
* @Date: 2022-09-04
*/
public interface ICar {
public void accept(ICarPartVisitor carPartVisitor);
}
④、定义具体元素类
这里使用了双分派,将具体状态传递到Benz中,完成第一次分派。
通过访问者调用具体的方法,并且将自身对象作为参数,完成第二次分派。
(红旗类也是如此)
package com.lyd.demo.element.car;
import com.lyd.demo.element.ICar;
import com.lyd.demo.visitor.ICarPartVisitor;
/**
* @Author: lyd
* @Description: 扩展的实体类 - 奔驰
* @Date: 2022-09-04
*/
public class Benz implements ICar {
@Override
public void accept(ICarPartVisitor carPartVisitor) {
carPartVisitor.visit(this); // 将本身带过去
}
}
⑤、定义数据结构
添加具体元素进来,通过循环遍历去调用各自的方法。
package com.lyd.demo.structure;
import com.lyd.demo.element.ICar;
import com.lyd.demo.visitor.ICarPartVisitor;
import java.util.LinkedList;
import java.util.List;
/**
* @Author: lyd
* @Description: 数据结构
* @Date: 2022-09-04
*/
public class ObjectStructure {
// 聚合
private List<ICar> cars = new LinkedList<ICar>();
// 添加到链表
public void attach(ICar car) {
this.cars.add(car);
}
// 缩减链表
public void remove(ICar car) {
this.cars.remove(car);
}
// 显示
public void display(ICarPartVisitor carPartVisitor) {
for (ICar car : cars) {
car.accept(carPartVisitor);
}
}
}
⑥、测试
通过数据结构将对象添加进去,在通过具体的访问者去统一调用方法
package com.lyd.demo.test;
import com.lyd.demo.element.car.Benz;
import com.lyd.demo.element.car.HongQi;
import com.lyd.demo.structure.ObjectStructure;
import com.lyd.demo.visitor.CarDisplayVisitor;
/**
* @Author: lyd
* @Description: 测试
* @Date: 2022-09-04
*/
public class VisitorTest {
public static void main(String[] args) {
// 创建对象
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Benz());
objectStructure.attach(new HongQi());
CarDisplayVisitor carDisplayVisitor = new CarDisplayVisitor();
objectStructure.display(carDisplayVisitor);
}
}
运行结果
👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得一键三连哦!👍
今天的内容理解不是那么简单,但实质上除了设计模式的思路,其实就是Java的面向对象知识,只要肯动手多敲,就容易理解。
💓德德小建议:
理解设计模式不是一件简单的事情,需要不断的学习和动手去练习,才能理解。只有掌握好设计模式,才能够真正的理解SpringAOP和Mybatis的底层原理。各位读者可以和我一样,动手敲一敲代码,甚至用不同的例子来做,通过debug一步一步调试,还有就是多看看别人的例子。能够有助于理解!谢谢各位观看指点!❤️ ❤️ ❤️