设计模式(23):访问者模式

定义

  • 表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变元素的类的前提下定义作用与这些元素的新操作。

模式动机

  • 对于存储在一个集合中的对象,他们可能具有不同的类型(即使有一个公共的接口),对于该集合中的对象,可以接受一类称为访问者的对象来访问,不同的访问者其访问方式也有所不同。

访问者模式角色

  • 抽象访问者: 一般通过visit方法声明可以访问哪写元素;
  • 具体访问者: 实现抽象访问者。访问元素的内容;
  • 抽象元素: 需要被访问的对象。一般有一个accept方法接受访问者方法;
  • 具体元素: 实现了抽象元素。在accept方法中调用访问者的visit方法;

开发中常见的场景

  • XML文挡解释器设计
  • 编译器的设计
  • 复杂集合对象的处理

总结

  • 访问者模式是GOF23种设计模式中最复杂的一种设计模式,一般在工作中不会使用访问者设计模式,也尽量不要使用访问者设计模式;如果用到了访问者设计模式,那就是必须要使用访问者设计模式啦。

代码实现

  • 抽象访问者
java 复制代码
/**
 * 抽象访问者
 */
public interface Visitor {

	void visit(ManElement manElement);
	
	void visit(WomanElement womanElement);
}
  • 具体访问者
java 复制代码
/**
 * 具体访问者NameVisitor
 */
public class NameVisitor implements Visitor {
	@Override
	public void visit(ManElement manElement) {
		System.out.println("名称:"+manElement.getName());
	}
	@Override
	public void visit(WomanElement womanElement) {
		System.out.println("名称:"+womanElement.getName());
	}
}
/**
 * 具体访问者GenderVisitor
 */
public class GenderVisitor implements Visitor {
	@Override
	public void visit(ManElement manElement) {
		System.out.println("性别:男");
	}
	@Override
	public void visit(WomanElement womanElement) {
		System.out.println("性别:女");
	}
}
/**
 * 具体访问者AgeVisitor
 */
public class AgeVisitor implements Visitor {
	@Override
	public void visit(ManElement manElement) {
		System.out.println("年龄:"+manElement.getAge());
	}
	@Override
	public void visit(WomanElement womanElement) {
		System.out.println("年龄:"+womanElement.getAge());
	}
}
  • 抽象元素
java 复制代码
/**
 * 抽象元素
 */
public interface Element {
	
	void accept(Visitor visitor);
	
}
  • 具体元素
java 复制代码
/**
 * 人
 */
public interface Person {
	String getName();
	Boolean isMan();
	Integer getAge();
}
/**
 * 具体元素ManElement 
 */
public class ManElement implements Person, Element{
	private String name;
	private Boolean isMan = true;
	private Integer age;
	public ManElement() {
	}
	public ManElement(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
	@Override
	public String getName() {
		return name;
	}
	@Override
	public Boolean isMan() {
		return isMan;
	}
	@Override
	public Integer getAge() {
		return age;
	}
	public Boolean getIsMan() {
		return isMan;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}
/**
 * 具体元素WomanElement 
 */
public class WomanElement implements Person,Element{
	private String name;
	private Boolean isMan = false;
	private Integer age;
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
	public WomanElement() {
	}
	public WomanElement(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String getName() {
		return name;
	}
	@Override
	public Boolean isMan() {
		return isMan;
	}
	@Override
	public Integer getAge() {
		return age;
	}
	public Boolean getIsMan() {
		return isMan;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}
  • 客户端调用
java 复制代码
public static void main(String[] args) {
	ManElement manElement = new ManElement("张三", 30);
	WomanElement womanElement = new WomanElement("翠花", 18);
	List<Element> elements = new ArrayList<>();
	elements.add(manElement);
	elements.add(womanElement);
	NameVisitor nameVisitor = new NameVisitor();
	GenderVisitor genderVisitor = new GenderVisitor();
	AgeVisitor ageVisitor = new AgeVisitor();
	for (Element element : elements) {
		element.accept(nameVisitor);
		element.accept(genderVisitor);
		element.accept(ageVisitor);
	}
}

更多设计模式学习:

设计模式(1):介绍

设计模式(2):单例模式

设计模式(3):工厂模式

设计模式(4):建造者模式

设计模式(5):原型模式

设计模式(6):桥接模式

设计模式(7):装饰器模式

设计模式(8):组合模式

设计模式(9):外观模式

设计模式(10):享元模式

设计模式(11):适配器模式

设计模式(12):代理模式

设计模式(13):模板方法模式

设计模式(14):命令模式

设计模式(15):迭代器模式

设计模式(16):观察者模式

设计模式(17):中介者模式

设计模式(18):状态模式

设计模式(19):策略模式

设计模式(20):责任链模式

设计模式(21):备忘录模式

设计模式(22):解释器模式

设计模式(23):访问者模式

相关推荐
Hui Baby12 小时前
springAi+MCP三种
java
hsjcjh12 小时前
【MySQL】C# 连接MySQL
java
敖正炀12 小时前
LinkedBlockingDeque详解
java
wangyadong31712 小时前
datagrip 链接mysql 报错
java
untE EADO12 小时前
Tomcat的server.xml配置详解
xml·java·tomcat
ictI CABL12 小时前
Tomcat 乱码问题彻底解决
java·tomcat
敖正炀12 小时前
DelayQueue 详解
java
敖正炀12 小时前
PriorityBlockingQueue 详解
java
shark222222213 小时前
Spring 的三种注入方式?
java·数据库·spring
陈煜的博客13 小时前
idea 项目只编译不打包,跳过测试,快速开发
java·ide·intellij-idea