一,訪問者模式
訪問者模式:
- 在被訪問的類裏面加一個對外提供接待訪問者的接口;
- 封裝一些作用於某種數據結構的各元素的操作,可以在不改變數據結構的前提下,定義作用於這些元素的新的操作;
- 將數據結構和數據操作分離,解決數據結構與數據操作的耦合性問題;
二,原理類圖
意圖: 封裝一些作用於某種數據結構的各元素的操作,可以在不改變數據結構的前提下,定義作用於這些元素的新的操作
適用性:
當需要對一個對象結構中的對象進行很多不同操作(這些操作可能沒有關聯),同時需要避免這些操作“污染”這些對象的類,可以考慮訪問者模式;
三,實例
雙分派:
首先,將Visitor作爲參數傳給Element(第一次分派);
然後在將Element自己傳給Visitor的方法中去執行(第二次分派);
Visitor接口: 抽象訪問者,爲ConcreteElement中的每個類聲明一個visit操作
package com.neei.visitor;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/14 20:24
* @Description: 遊學網
* @throws:
*/
public interface Action {
/**
* 男性評分
*
* @param man
*/
void getManResult(Man man);
/**
* 女性評分
*
* @param woMan
*/
void getWoManResult(WoMan woMan);
}
ConcreteVisitor: 具體的訪問者,實現每個Visitor聲明的操作,是每個操作的實現部分。
package com.neei.visitor;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/14 20:30
* @Description: 遊學網
* @throws:
*/
public class Success implements Action {
@Override
public void getManResult(Man man) {
System.out.println(man.getName() + ":機智過人");
}
@Override
public void getWoManResult(WoMan woMan) {
System.out.println(woMan.getName() + ":機智過人");
}
}
public class Fail implements Action {
@Override
public void getManResult(Man man) {
System.out.println(man.getName() + ":技不如人");
}
@Override
public void getWoManResult(WoMan woMan) {
System.out.println(woMan.getName() + ":技不如人");
}
}
public class Equal implements Action {
@Override
public void getManResult(Man man) {
System.out.println(man.getName() + ":不相上下");
}
@Override
public void getWoManResult(WoMan woMan) {
System.out.println(woMan.getName() + ":不相上下");
}
}
ObjectStructure: 能夠枚舉元素,提供一個高層的接口,允許訪問者訪問元素;
package com.neei.visitor;
import java.lang.invoke.VolatileCallSite;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/14 20:40
* @Description: 遊學網
* @throws:
*/
public class ObjectStructure {
private List<Person> list = new LinkedList<>();
public void add(Person person) {
list.add(person);
}
public void deleted(Person person) {
list.remove(person);
}
public void display(Action action) {
for (Person person : list) {
person.accept(action);
}
}
}
Element接口: 定義accept方法,接收一個訪問者對象;
package com.neei.visitor;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/14 20:24
* @Description: 遊學網
* @throws:
*/
public abstract class Person {
/**
* 提供訪問方法
*
* @param action
*/
abstract void accept(Action action);
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
}
ConcreteElement: 具體元素,實現accept方法;
package com.neei.visitor;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/14 20:29
* @Description: 遊學網
* @throws:
*/
public class WoMan extends Person {
public WoMan(String name) {
super(name);
}
/**
* 雙分派
* @param action
*/
@Override
void accept(Action action) {
action.getWoManResult(this);
}
}
public class Man extends Person {
public Man(String name) {
super(name);
}
/**
* 雙分派
* @param action
*/
@Override
void accept(Action action) {
action.getManResult(this);
}
}
四,源碼分析
JDK源碼中使用的訪問者模式,如java.nio.file.FileVisitor;