系列文章目录
前言
前一篇文章中介绍了ASM中的一些基本操作,本篇文章的主题是介绍一下ASM中所使用的设计模式,在了解完本篇文章的内容后,相信大家会对ASM有一些新的认识和了解。
一、访问者模式
ASM库中使用的设计模式为访问者模式,该模式的主要目的是要将数据和对数据的操作进行一个分离,简单的来说,就是针对不同的数据,都有一个单独的数据操作对象。使用这种设计模式,可以规避多重的if-else使用来进行数据类型判断,他的UML类图可以描述为:
从上图可以看出,我们可以针对不同的数据类型,在真正的访问者(AVisitor)中重写不同的visit方法,根据不同的参数类型,可以调用不同的方法,这样就省去了通过if-else进行类型判断的过程,数据的读取可以由数据类中accept使用访问者对该类中的数据进行操作,上述的过程可以由如下代码表示:
首先创建一个接口Data:
public interface Data {
void accept(Visitor visitor);
}
有两个Data的实现类,AData和BData:
public class AData implements Data{
int a1 = 100;
int a2 = 200;
int a3 = 300;
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class BData implements Data {
int b1 = 100;
int b2 = 200;
int b3 = 300;
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
一个数据的集合,同时包含一个读取数据的方法:
public class DataStruct {
AData aData = new AData();
BData bData = new BData();
void readData(Visitor visitor) {
aData.accept(visitor);
bData.accept(visitor);
}
}
以上就是和数据有关的类,以下为与数据操作相关的类:
public interface Visitor {
void visit(AData data);
void visit(BData data);
}
数据访问者的实现类AVisitor:
public class AVisitor implements Visitor {
@Override
public void visit(AData data) {
System.out.println("a1: " + data.a1 + " a2: " + data.a2 + " a3: " + data.a3);
}
@Override
public void visit(BData data) {
System.out.println("b1: " + data.b1 + " b2: " + data.b2 + " b3: " + data.b3);
}
}
然后我们创建一个client,如下:
public class Client {
public static void main(String[] args) {
DataStruct data = new DataStruct();
data.readData(new AVisitor());
}
}
最后可以得到打印输出:
a1: 100 a2: 200 a3: 300
b1: 100 b2: 200 b3: 300
可以看出通过这样的方式对数据进行操作,可以实现数据和数据操作对象的解耦。
二、ASM实例分析
在ASM中,我们会看到如下代码:
ClassPrinter cp = new ClassPrinter(); //ClassVisitor的实现类
ClassReader cr = new ClassReader("java.lang.Boolean");
cr.accept(cp, 0);
其中ClassPrinter为ClassVisitor的一个实现类,如下:
class ClassPrinter extends ClassVisitor {
public ClassPrinter() {
super(ASM4);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
System.out.println(name + " extends " + superName + "{");
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
System.out.println(" " + descriptor + " " + name);
return super.visitField(access, name, descriptor, signature, value);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
System.out.println(" " + name + descriptor);
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
@Override
public void visitEnd() {
super.visitEnd();
System.out.println("}");
}
}
这里就对应了第一节中的Visitor和AVisitor。ClassReader就是数据类,对应了Data,可以调用他的accept方法使用Visitor来访问数据。
除此以外,在ASM中一个很有意思的地方是可以将多个ClassVisitor组合起来进行使用,这里他是在每个ClassVisitor的成员变量中还放了一个ClassVisitor对象。也就是说,可以在构造数据的时候,可以使用成员变量中的ClassVisitor的访问逻辑,当然在此基础上,也可以添加自己的逻辑,比如说,在ASM学习系列(一) 中,移除或增添变量的时候,还使用了TraceClassVisitor这个类的访问数据的功能。
总结
以上就是这篇文章的内容,本文主要介绍了ASM所使用的设计模式,在了解了该模式后,可以对理解ASM的架构和使用ASM都有很大的帮助。