• Visitor
  • 内部结构不变,访问方式扩展
    • interface Visitor {
          void visitCpu(CPU cpu);
      } 
      class Visitor1 implements Visitor {
          double price = 0.0;
          @Override
          void visitCpu(CPU cpu) {
              price += cpu.getPrice() * 0.9;
          }
      }
      class Computer {
          Part cpu;
          void accept(Visitor v) {
              this.cpu.accept(v);
          }
      }
      abstract class Part {
          abstract void accept(Visitor v);
          abstract double getPrice();
      }
      class CPU extends Part {
          @Override
          void accept(Visitor v){
              v.visitCpu(this);
          }
      }
       
      Visitor p = new Visitor1();
      new Computer().accept(p);
      p.price;
  • Java类AST编译器Visitor, ASM
    • // 打印
      class ClassPrinter extends ClassVisitor {
          @Override
          MethodVisitor visitMethod(){
              print(name + "()");
              retrun null;
          }
      }
      ClassPrinter cp = new ClassPrinter();
      ClassReader cr = new ClassReader("java.lang.Runnable");
      cr.accept(cp, 0);
       
      // 生成类
      ClassWriter cw = new ClassWriter(0);
      cw.visitMethod(ACC_PULIC + ACC_ABSTRACT, "compareTo", "(Ljava/lang/Object;)I", null, null).visitEnd();
      cw.visitEnd();
      MyClassLoader cl = new MyClassLoader();
      byte[] b = cw.toByteArray();
      Class c = cl.defineClass("pkg.Comparable", b, 0, b.length);
       
      // 代理类
      ClassReader cr = new ClassReader();
      ClassWriter cw = new ClassWriter(0);
      ClassVisitor cv = new ClassVisitor(ASM4, cw) {
          @Override
          public MethodVisitor visitMethod() {
              MethodVisitor mv = super.visitMethod(); 
              return new MethodVisitor(ASM4, mv) {
                  @Override
                  public void visitCode(){
                      visitMethodInsn(INVOKESTATIC, "TimeProxy", "before", "()v", false);
                      super.visitCode();
                  }
              }
          }
      };
      cr.accept(cv, 0);
      cw.toByteArray();