设计模式-访问者模式
背景
记得去北京旅游的时候,有一件痛苦的事情就是上厕所,真是件非常痛苦的事情,有时候人一多,女厕所人太多了,直接跑到男的这边来了,搞得很无语,第一次看到这种壮观....不过上厕所男女有别倒是类似于访问者,不同的人根据不同的身份访问不同的厕所。
访问者模式是什么?
访问者模式(Visitor Pattern)是一个行为模式,封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。
角色
Visitor:访问者接口,为所有的访问者对象声明一个visit方法,用来代表为对象结构添加的功能,理论上可以代表任意的功能。
ConcreteVisitor :具体访问者,主要是实现方法者的实现;
Element:抽象元素:接口或者抽象类,主要声明顶层的设计,接受访问的操作。
ConcreteElement :具体的元素或对象,提供自数据和功能给访问者使用。
ObjectStruture:对象结构,通常包含多个访问对象。
访问者模式可以干嘛?
访问者模式主要解决的一个问题就是不用区分元素是哪种,而根据访问者的不同信息返回相应的信息,就好比文件夹中有文件,通过访问者的信息来判断你是文件还是文件夹。并也不用改变原有结构而很容易就实现了这种区别。
优点:
遵循设计规则:符合单一职责原则
拓展性强:可以拓展多个元素,不同的访问器
缺点:
保密性不好:对访问者公布了细节,违反了迪米特原则。
个人理解:
访问者就像不同的性别进入不同的厕所,人是元素,性别是访问类型。
访问者模式类图
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
实现代码
/**
* @ClassName IVisitor
* @Author csh
* @Description 抽象访问者(Visitor)
* @Date 2020/6/22
**/
public interface IVisitor {
void visit(Person person);
}
/**
* @ClassName Person
* @Author csh
* @Description 人 抽象元素(Element)
* @Date 2020/6/22
**/
public abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//抽象访问接口
public abstract void accept(IVisitor visitor);
}
/**
* @ClassName Male
* @Author csh
* @Description 具体元素(ConcreteElement )
* @Date 2020/6/22
**/
public class Male extends Person {
public Male(String name) {
super(name);
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* @ClassName Woman
* @Author csh 具体元素(ConcreteElement )
* @Description
* @Date 2020/6/22
**/
public class Woman extends Person {
public Woman(String name) {
super(name);
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
/**
* @ClassName ManVisitor
* @Author csh 具体访问者(ConcreteVisitor)
* @Description
* @Date 2020/6/22
**/
public class ManVisitor implements IVisitor {
@Override
public void visit(Person person) {
if(person instanceof Male){
System.out.println(person.getName()+"进入男厕所!");
}
}
}
/**
* @ClassName WomanVisitor
* @Author csh 具体访问者(ConcreteVisitor)
* @Description
* @Date 2020/6/22
**/
public class WomanVisitor implements IVisitor {
@Override
public void visit(Person person) {
if(person instanceof Woman){
System.out.println(person.getName()+"进入女厕所!");
}
}
}
/**
* @ClassName ObjectStructure
* @Author csh ObjectStruture(对象结构)
* @Description
* @Date 2020/6/22
**/
public class ObjectStructure {
private List<Person> personList = new ArrayList<Person>();
public void action(IVisitor visitor){
for (Person person : personList) {
person.accept(visitor);
}
}
public void add(Person person){
personList.add(person);
}
public void remove(Person person){
personList.remove(person);
}
}
/**
* @ClassName Client
* @Author csh
* @Description 演示访问者模式,不能人进入不同厕所
* @Date 2020/6/22
**/
public class Client {
public static void main(String[] args) {
Person man1 = new Male("hong1");
Person man2 = new Male("hong2");
Person woman1 =new Woman("min1");
Person woman2= new Woman("min2");
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.add(man1);
objectStructure.add(man2);
objectStructure.add(woman1);
objectStructure.add(woman2);
//男厕所
IVisitor man = new ManVisitor();
//女厕所
IVisitor woman = new WomanVisitor();
//进入男厕所
objectStructure.action(man);
//进入女厕所
objectStructure.action(woman);
}
}
结果
hong1进入男厕所!
hong2进入男厕所!
min1进入女厕所!
min2进入女厕所!
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
访问者在实际项目中除了非常稳定的数据结构者会使用,并且该模式相对来说比较绕,一般代码可读性不是很高并且一般都用于系统重构中,最大的好处就是结构统一,在实际应用中,其实还有通过元素本身来做进一步业务处理。
使用到访问者模式的场景
Java8 新特性之集合:forEach(Consumer<? super T> action)
- ASM基本配置问题(r5笔记第89天)
- 如何上手使用 Facebook 的开源平台 Detectron?
- 多线程编程学习三(线程间通信).
- 关于create database语句在10g,11g中的不同(r5笔记第88天)
- Web开发模式【Mode I 和Mode II的介绍、应用案例】
- 多线程编程学习四(Lock 的使用)
- Android编程规范
- 干货 | 深入分析Object.wait/notify实现机制
- 关于ORA-01555的问题分析(r5笔记第87天)
- 项目工具类
- AJAX常见面试题
- 干货 | Tomcat类加载机制触发的Too many open files问题分析
- 并行查询缓慢的问题分析(r5笔记第86天)
- Swagger文档转Word 文档
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法