本文链接:https://blog.csdn.net/feather_wch/article/details/131756394
1、访问者模式(Visitor Pattern)属于行为型模式
2、定义:在类的内部结构不变的情况下,不同的访问者访问这个对象都会呈现出不同的处理方式。
为了解决类结构不变但操作处理逻辑易变的问题,把对数据的操作都封装到访问者类中,我们只需要调用不同的访问者,而无需改变改变结构类。
【设计模式】访问者模式,不愧是最复杂的设计模式之一!
3、违背了开闭原则
访问者模式的基本结构包括以下几个角色:
accept(Visitor visitor)
。 ==> 比如是饮品visitor.visit(this)
。==> 比如是奶茶、果茶visit(ConcreteElement element)
。==> 会员奶茶店维护不同的奶茶、果茶,对于同一种产品,不同的会员会拥有不同的折扣。
public interface Beverage {
void accept(Visitor visitor); // 访问
int getPrice(); // 获得价格
}
实现饮料接口,accept还是交给visitor自己去处理
public class ShengShengWuLong implements Beverage {
int price;
public ShengShengWuLong(int price) {
this.price = price;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public int getPrice() {
return price;
}
}
public class YoulanLatte implements Beverage {
int price;
public YoulanLatte(int price) {
this.price = price;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public int getPrice() {
return price;
}
}
根据具体元素的数量,定义visit方法
public abstract class Visitor {
abstract void visit(ShengShengWuLong wulong);
abstract void visit(YoulanLatte latte);
}
白银会员、黄金会员、钻石会员
实现visit方法,自定义处理逻辑。
public class SilverClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("白银客户 喝到:"+wulong.getClass().getSimpleName() + " 9折:" + (0.9 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("白银客户 喝到:"+latte.getClass().getSimpleName() + " 9折:" + (0.9 * latte.getPrice()));
}
}
public class GoldClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("黄金客户 喝到:"+wulong.getClass().getSimpleName() + " 8折:" + (0.8 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("黄金客户 喝到:"+latte.getClass().getSimpleName() + " 8折:" + (0.8 * latte.getPrice()));
}
}
public class DiamondClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("钻石客户 喝到:"+wulong.getClass().getSimpleName() + " 7折:" + (0.7 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("钻石客户 喝到:"+latte.getClass().getSimpleName() + " 7折:" + (0.7 * latte.getPrice()));
}
}
public class Store {
List<Beverage> drinks = new ArrayList<>();
public void addBeverage(Beverage beverage){
drinks.add(beverage);
}
public void accept(Visitor visitor){
for (Beverage beverage : drinks) {
beverage.accept(visitor);
}
}
}
测试类
public class Main {
public static void main(String[] args) {
Store store = new Store();
store.addBeverage(new ShengShengWuLong(32));
store.addBeverage(new YoulanLatte(26));
store.accept(new SilverClient());
store.accept(new GoldClient());
store.accept(new DiamondClient());
}
}
1、ASM是什么?=>ASM框架通过改写或直接写出字节码(class文件)去生成新的类
相对于JDK动态代理(Proxy.newProxyInstance)性能更高,因为后者是利用了反射,而前者直接生成想要的类行为。
2、为什么ASM要使用访问者模式?
3、ASM是如何实现的?
- 通过找到固定方法区,修改方法区代码。
- 需要如何变换,定义访问者去决定操作逻辑
4、ASM组成部分和访问者对照表
1、抽象元素(Element)
2、具体元素(ConcreteElement)
3、抽象访问者(Visitor) => ClassVisitor、MethodVisitor、FieldVisitor、SignatureVisitor
4、具体访问者(ConcreteVisitor) => ClassWriter、AdviceAdapter(MethodVisitor)
5、对象结构(ObjectStructure)=> ClassReader
MethodVisitor也是一个抽象访问者,它定义了对方法中的指令、变量、标签、异常等元素的访问操作,通常也是visit(ConcreteElement element)。MethodVisitor也可以有多个具体的子类,比如AdviceAdapter、GeneratorAdapter等,它们都实现了对方法中的元素的访问操作。AdviceAdapter负责在方法的开始和结束处插入代码,GeneratorAdapter负责生成常用的指令。
ClassReader
->读取到一个类
->ClassVisitor.visit 传递一些类的信息
->读取到一个字段
->ClassVisitor.visitField 传递一些字段的信息
->读取到一个方法
->ClassVisitor.visitMethod方法 传递一些方法的信息
->返回MethodVisitor对象:定义了对方法中的指令、变量、标签、异常等元素的访问操作
->继续读取这个方法中的元素
->MethodVisitor.visit方法 传递一些元素的信息