[8] [行为变化] ( 2 ) 访问者 visitor

总结

  • 为什么需要访问器模式?
    在软件构建过程中,
    有些需求的变化,
    会导致类层次结构需要添加某些新的行为,
    进而导致源代码的更改,
    这违背了开闭原则.
    image


  • 如何在不改源码的前提下,在运行时添加新行为,避免上述问题?
    使用visitor模式
    (将编译时扩展行为向后延迟,转化为运行时扩展行为)


  • GOF定义?
    表示一个作用于某对象结构中的各元素的操作.
    使得可以在不改变(稳定)各element类的前提下,
    定义(扩展)作用于这些element的新操作(变化)


  • visitor的实现思路?
    主要作用将数据结构和数据操作分离,
    使操作集合可以独立于数据结构变化,
    在不改变数据结构的前提下,
    通过添加新的操作来扩展功能.
    (添加新的Visitor就是添加新的操作)


  • 使用visitor模式的严格前提?
    定义Visitor的时候必须知道Element有几个子类.
    如果不能确定Element子类的个数,
    Visitor就没法稳定下来.
    所以Visitor模式只适用于Element子类稳定的情况..
    .
    换一个具体的说法:
    添加新的数据结构, 所有的访问者都要被修改.
    因为Visitor类的方法的参数是Element,
    Visitor依赖于Element,
    修改Element的数据结构,
    Visitor内对Element的操作也要改.


  • 应用案例?
    文档转换(用visitor模式遍历markdown文档的元素, 生成对应的html/pdf元素)


  • 主要组件?
    Element
    ConcreteElement
    Visitor
    ConcreteVisitor




java例子

重构前

package v32_visitor.java;

interface Shape {
    void draw();
    void resize();
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing a circle");
    }

    public void resize() {
        System.out.println("Resizing a circle");
    }
}

class Rectangle implements Shape {
    public void draw() {
        System.out.println("Drawing a rectangle");
    }

    public void resize() {
        System.out.println("Resizing a rectangle");
    }
}

public class ShapeMain1 {
    public static void main(String[] args) {
        Shape circle = new Circle();
        Shape rectangle = new Rectangle();

        circle.draw();
        rectangle.draw();

        circle.resize();
        rectangle.resize();
    }
}





重构后

package v32_visitor.java;

interface Shape {
    void accept(Visitor visitor);
}

class Circle implements Shape {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Rectangle implements Shape {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

interface Visitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}

class DrawVisitor implements Visitor {
    public void visit(Circle circle) {
        System.out.println("Drawing a circle");
    }

    public void visit(Rectangle rectangle) {
        System.out.println("Drawing a rectangle");
    }
}

class ResizeVisitor implements Visitor {
    public void visit(Circle circle) {
        System.out.println("Resizing a circle");
    }

    public void visit(Rectangle rectangle) {
        System.out.println("Resizing a rectangle");
    }
}

public class ShapeMain2 {
    public static void main(String[] args) {
        Shape circle = new Circle();
        Shape rectangle = new Rectangle();

        Visitor drawVisitor = new DrawVisitor();
        Visitor resizeVisitor = new ResizeVisitor();

        circle.accept(drawVisitor);
        rectangle.accept(drawVisitor);

        circle.accept(resizeVisitor);
        rectangle.accept(resizeVisitor);
    }
}





image




image




c++例子

重构前

#include <iostream>
using namespace std;

class Visitor;

// 接口
class Element {
 public:
  virtual void Func1() = 0;

  virtual void Func2(int data) = 0;
  virtual void Func3(int data) = 0;
  //...

  virtual ~Element() {}
};

class ElementA : public Element {
 public:
  void Func1() override {
    //...
  }

  void Func2(int data) override {
    //...
  }
};

class ElementB : public Element {
 public:
  void Func1() override {
    //***
  }

  void Func2(int data) override {
    //***
  }
};





重构后

#include <iostream>
using namespace std;

class Visitor;

class Element {
 public:
  virtual void accept(Visitor& visitor) = 0;  //第一次多态辨析

  virtual ~Element() {}
};

class ElementA : public Element {
 public:
  void accept(Visitor& visitor) override { visitor.visitElementA(*this); }
};

class ElementB : public Element {
 public:
  void accept(Visitor& visitor) override {
    visitor.visitElementB(*this);  //第二次多态辨析
  }
};

class Visitor {
 public:
  virtual void visitElementA(ElementA& element) = 0;
  virtual void visitElementB(ElementB& element) = 0;

  virtual ~Visitor() {}
};

//==================================

//扩展1
class Visitor1 : public Visitor {
 public:
  void visitElementA(ElementA& element) override {
    cout << "Visitor1 is processing ElementA" << endl;
  }

  void visitElementB(ElementB& element) override {
    cout << "Visitor1 is processing ElementB" << endl;
  }
};

//扩展2
class Visitor2 : public Visitor {
 public:
  void visitElementA(ElementA& element) override {
    cout << "Visitor2 is processing ElementA" << endl;
  }

  void visitElementB(ElementB& element) override {
    cout << "Visitor2 is processing ElementB" << endl;
  }
};

int main() {
  Visitor2 visitor;
  ElementB elementB;
  elementB.accept(visitor);  // double dispatch

  ElementA elementA;
  elementA.accept(visitor);

  return 0;
}





image




image




posted @ 2023-12-09 02:48  qwertzxc  阅读(11)  评论(0)    收藏  举报