在结构不变的情况下动态改变对于内部元素的动作 专业的设计模式(工作中很少用) 编译器的例子:抽象语法树—->语法分析—->visitor模式

情景引入

中关村装机 一台机器三部分组成:cpu、内存、主板 针对不同的客户(学生、社畜、批发)给出不同德折扣

UML类图

image.png

实现

accept()方法:接待不同客户(if实现不好,不光要耦合到accept中去,而且新的客户来要修改的太多) cpu等组件去接待来访者,但接待策略让来访者自己实现策略 visitor.visitCpu();实现不同的折扣并计算总价 accept(v)方法是一个固定模式v.visit(); 好处:电脑那个类就不用变了 格式、内部结构固定的情况下用visitor 电脑内部组件不断增加的情况下visitor模式就不适合了(不适用) visitor模式访问的是结构固定的,定死的结构 思想:将不同组件中的if-else抽取到一个类中,通过多态决定具体的业务处理逻辑 将if-else的变化抽象出来,抽象到一个单独的visitor接口中

  1. package com.mashibing.dp.visitor;
  2. public class Computer {
  3. // 组合/聚合
  4. ComputerPart cpu = new CPU();
  5. ComputerPart memory = new Memory();
  6. ComputerPart board = new Board();
  7. public void acccept(Visitor v) {
  8. this.cpu.accept(v);
  9. this.memory.accept(v);
  10. this.board.accept(v);
  11. }
  12. public static void main(String[] args) {
  13. PersonelVisitor p = new PersonelVisitor();
  14. new Computer().acccept(p);
  15. System.out.println(p.totalPrice);
  16. }
  17. }
  18. abstract class ComputerPart {
  19. abstract void accept(Visitor v);
  20. //some other operations eg:getName getBrand
  21. abstract double getPrice();
  22. }
  23. class CPU extends ComputerPart {
  24. @Override
  25. void accept(Visitor v) {
  26. // 将this作为参数传到方法中
  27. // 这里的this指cpu对象,传进去后就能够进行相应的处理(获取价钱、测试性能、体验之类的……)
  28. v.visitCpu(this);
  29. }
  30. @Override
  31. double getPrice() {
  32. return 500;
  33. }
  34. }
  35. class Memory extends ComputerPart {
  36. @Override
  37. void accept(Visitor v) {
  38. v.visitMemory(this);
  39. }
  40. @Override
  41. double getPrice() {
  42. return 300;
  43. }
  44. }
  45. class Board extends ComputerPart {
  46. @Override
  47. void accept(Visitor v) {
  48. v.visitBoard(this);
  49. }
  50. @Override
  51. double getPrice() {
  52. return 200;
  53. }
  54. }
  55. interface Visitor {
  56. void visitCpu(CPU cpu);
  57. void visitMemory(Memory memory);
  58. void visitBoard(Board board);
  59. }
  60. class PersonelVisitor implements Visitor {
  61. double totalPrice = 0.0;
  62. @Override
  63. public void visitCpu(CPU cpu) {
  64. totalPrice += cpu.getPrice()*0.9;
  65. }
  66. @Override
  67. public void visitMemory(Memory memory) {
  68. totalPrice += memory.getPrice()*0.85;
  69. }
  70. @Override
  71. public void visitBoard(Board board) {
  72. totalPrice += board.getPrice()*0.95;
  73. }
  74. }
  75. class CorpVisitor implements Visitor {
  76. double totalPrice = 0.0;
  77. @Override
  78. public void visitCpu(CPU cpu) {
  79. totalPrice += cpu.getPrice()*0.6;
  80. }
  81. @Override
  82. public void visitMemory(Memory memory) {
  83. totalPrice += memory.getPrice()*0.75;
  84. }
  85. @Override
  86. public void visitBoard(Board board) {
  87. totalPrice += board.getPrice()*0.75;
  88. }
  89. }

编译器专业领域

  • 抽象语法树AST:根据树来做具体操作
    • 类型检查
    • 生成中间代码
    • 不同动作访问抽象语法树

      AST

      image.png

      上图根节点加号的右孩子改为9

传统结构

image.png

visitor模式

image.png

每个Node可以accept一个或者一堆的visitor

Visitor模式的应用:asm字节码二进制处理工具(java的汇编—->分析字节码文件中的语法分析树) ===> 详见下一篇ASM入门

🤏随想

  1. 建议去读gof的设计模式:可复用的设计
  2. operator操作符 operand操作数