访问者模式

1991/6/26 行为型

# 定义

访问者模式(Visitor Pattern):在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。许你通过访问者对象来获取或修改一个或多个被保护的对象的 state。

访问者模式的关键点如下:

  1. 定义一个访问者对象,它包含一个或多个对象。
  2. 定义一个接口,用于定义访问者对象的操作。
  3. 在接口中声明一个方法,用于获取对象的状态。
  4. 在接口中声明一个方法,用于修改对象的状态。
  5. 将访问者对象与需要获取或修改的对象建立引用关系。
  6. 访问者对象可以访问或修改它所引用的对象的状态。

# 用途

稳定的数据结构和易变的操作耦合问题。

访问者模式是一种非常有用的设计模式,它可以帮助我们抽象出对象之间的访问关系,并可以方便地实现多态。访问者模式的应用场景包括但不限于:

  1. 需要对外部用户进行状态持久化存储的对象,如数据库中的记录。
  2. 需要对对象的状态进行同步的对象,如多用户并发访问的对象。
  3. 需要对对象的状态进行修改的对象,如计数器。
  4. 需要对对象的状态进行优先级排序的对象,如用户等级查询系统。
  5. 需要对对象的状态进行事务的对象,如分布式事务。

# 示例

以显示计算机的组成部分为例,主要分五步实现:

  1. 定义一个表示元素的接口。

    public interface ComputerPart {
        public void accept(ComputerPartVisitor computerPartVisitor);
    }
    
    1
    2
    3
  2. 创建扩展了上述类的实体类。Keyboard、Monitor、Mouse、Computer

    public class Computer implements ComputerPart {
    
        private ComputerPart[] parts;
    
        public Computer() {
            this.parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()};
        }
    
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            for (ComputerPart part : parts) {
                part.accept(computerPartVisitor);
            }
            computerPartVisitor.visit(this);
        }
    }
    public class Mouse implements ComputerPart {
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            computerPartVisitor.visit(this);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
  3. 定义一个表示访问者的接口。

    public interface ComputerPartVisitor {
    
        public void visit(Computer computer);
    
        public void visit(Mouse mouse);
    
        public void visit(Keyboard keyboard);
    
        public void visit(Monitor monitor);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  4. 创建实现了上述类的实体访问者。

    public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
    
        @Override
        public void visit(Computer computer) {
            Log.e("---", "Displaying Computer.");
        }
    
        @Override
        public void visit(Mouse mouse) {
            Log.e("---", "Displaying Mouse.");
        }
    
        @Override
        public void visit(Keyboard keyboard) {
            Log.e("---", "Displaying Keyboard.");
        }
    
        @Override
        public void visit(Monitor monitor) {
            Log.e("---", "Displaying Monitor.");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
  5. 使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。

    ComputerPart computer = new Computer();
        computer.accept(new ComputerPartDisplayVisitor());
        /*
         *打印:
         *---: Displaying Mouse.
         *---: Displaying Keyboard.
         *---: Displaying Monitor.
         *---: Displaying Computer.
         */
    
    1
    2
    3
    4
    5
    6
    7
    8
    9