访问者模式把数据和对数据的操作松耦合化了,使得对数据的操作可以自由演化,使得表现出不同的数据格式。
访问者模式精髓:在不改变主体的前提下,通过使用不同的操作方式而使主体本身表现出不同的效果!
访问者模式 将一组对象的访问行为 抽象出来,使得相同的对象通过改变访问者而使得对象自己能够完成不同的操作。
著名的字节码操控工具 asm 就是使用访问者模式实现了优雅的编程模型。
由于类文件的格式是固定的,包括属性、方法、注解等等,对这些信息的操作可以抽象到一个访问者的行为中,这样不同的访问者可以不同的方式进行处理,如添加访问者可添加一些信息、修改访问者可修改一些信息等等。
场景:调色板上由三原色,红、绿、蓝,使用不同的调色方式可以使得调出不同的颜色来。
分析:原色由三种,固定不变,设置不同的比例大小,可产生多种其它颜色,红色数据+绿色数据 可使调色板展示出黄色,绿色数据+蓝色数据+红色数据 可使调色板展示出白色,
蓝色数据+红色数据 可使调色板展示出紫色,对相同的数据进行不同的访问得出不同的效果,可以使用访问者模式实现。
设计:
示例代码:
package netty_ws;
interface ColorData {
// 将对自己的处理权交给访问者
void accept(ColorMaker colorMaker);// 只是接受一个访问者,不关心访问者如何处理自己
}
class RedData implements ColorData {
private int s;
public void setState(int s) {
this.s = s;
}
public int getState() {
return s;
}
public void accept(ColorMaker colorMaker) {
System.out.println("红色数据接受处理");
colorMaker.visit(this);//转移到访问者中处理
}
}
class GreenData implements ColorData {
private int s;
public void setState(int s) {
this.s = s;
}
public int getState() {
return s;
}
public void accept(ColorMaker colorMaker) {
System.out.println("绿色数据接受处理");
colorMaker.visit(this);//转移到访问者中处理
}
}
class BlueData implements ColorData {
private int s;
public void setState(int s) {
this.s = s;
}
public int getState() {
return s;
}
public void accept(ColorMaker colorMaker) {
System.out.println("蓝色数据接受处理");
colorMaker.visit(this);//转移到访问者中处理
}
}
interface ColorMaker {
//拥有访问各具体元素的能力
void visit(RedData redData);
void visit(GreenData greenData);
void visit(BlueData blueData);
}
/**
* 红色数据+绿色数据 可配置出黄色
*/
class YellowMaker implements ColorMaker {
//对具体的各个元素作处理
public void visit(RedData redData) {
redData.setState(1);
}
public void visit(GreenData greenData) {
greenData.setState(1);
}
public void visit(BlueData blueData) {
blueData.setState(0);
}
}
/**
* 绿色数据+蓝色数据+红色数据 可配置出白色
*/
class WhiteMaker implements ColorMaker {
//对具体的各个元素作处理
public void visit(RedData redData) {
redData.setState(1);
}
public void visit(GreenData greenData) {
greenData.setState(1);
}
public void visit(BlueData blueData) {
blueData.setState(1);
}
}
/**
* 蓝色数据+红色数据 可配置出紫色
*/
class PurpleMaker implements ColorMaker {
//对具体的各个元素作处理
public void visit(RedData redData) {
redData.setState(1);
}
public void visit(GreenData greenData) {
greenData.setState(0);
}
public void visit(BlueData blueData) {
blueData.setState(1);
}
}
/**
* 拥有基础数据的主体,通过使用不同的调色方式进而得出不同的效果,
* 即使用不同的访问者,动态增加新的表现!
*/
class Palette {
// 可以处理的数据
RedData redData = new RedData();
GreenData greenData = new GreenData();
BlueData blueData = new BlueData();
/**
* 访问基础颜色数据,制作不同的颜色,
* 颜料库由三种颜料,ColorMaker必需能够处理这三种颜料,所以它需要知晓所有具体的颜料类型
*/
public void makeColor(ColorMaker maker) {
// 可能的使用方式:
// for (ColorData colorData:colorDatas) {
/**
* 注意这里不能由ColorMaker主动发起访问,因为实际上我们也不知道它的具体visit能力
*/
// maker.visit(colorData);
// 巧妙之处的入口体现
// colorData.accept(maker);
// }
// 接受访问
//注意这里不能由ColorMaker主动发起访问,因为实际上我们也不确定它的具体visit能力和实际逻辑
redData.accept(maker);
greenData.accept(maker);
blueData.accept(maker);
showResult();
}
/**
* 通过使用不同的访问者,自身可动态表现出不同的效果,这即是访问者模式的精髓
*/
public void showResult() {
String colorMatching =
String.valueOf(redData.getState()) +
greenData.getState() +
blueData.getState();
switch (colorMatching) {
case "110":
System.out.println("===========表现:黄色");
break;
case "111":
System.out.println("===========表现:白色");
break;
case "101":
System.out.println("===========表现:紫色");
break;
default:
System.out.println("未知颜色");
break;
}
}
}
/**
* 测试:访问者模式
*/
public class Test {
public static void main(String[] args) {
Palette palette = new Palette();
palette.makeColor(new WhiteMaker()); // 使用白色访问者,制作白色
palette.makeColor(new YellowMaker()); // 使用换色黄色者,制作黄色
palette.makeColor(new PurpleMaker()); // 使用紫色访问者,制作紫色
}
}
输出:
红色数据接受处理
绿色数据接受处理
蓝色数据接受处理
===========表现:白色
红色数据接受处理
绿色数据接受处理
蓝色数据接受处理
===========表现:黄色
红色数据接受处理
绿色数据接受处理
蓝色数据接受处理
===========表现:紫色