UP | HOME

访问者模式

Table of Contents

访问者模式:把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构,适用于数据结构相对稳定算法又易变化的系统

UML

visitor.png

Java

  • 定义访问者接口Vistor(操作):
    public interface Visitor {
        void visit(Subject sub);
    }
    
  • 定义被访问者Subject(数据结构),通过增加不同的Vistor,调用accept方法可达到动态添加新的操作
    public abstract class Subject {
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
    
        public abstract String getSubject();
    }
    
  • 实现不同的Subject类:
    public class MySubject1 extends Subject {
        @Override
        public String getSubject() {
            return "subject1";
        }
    }
    
    public class MySubject2 extends Subject {
        @Override
        public String getSubject() {
            return "subject2";
        }
    }
    
  • 实现不同的Vistor类:
    public class MyVisitor1 implements Visitor {
        @Override
        public void visit(Subject sub) {
            System.out.println("visitor1 visits the " + sub.getSubject());
        }
    }
    
    public class MyVisitor2 implements Visitor{
        @Override
        public void visit(Subject sub) {
            System.out.println("visitor2 visit the " + sub.getSubject());
        }
    }
    
  • 测试代码:
    public class VisitorTest {
        public static void main(String[] args) {
            Visitor visitor = new MyVisitor1();
            Subject sub = new MySubject1();
            sub.accept(visitor);
    
            sub = new MySubject2();
            sub.accept(visitor);
    
            visitor = new MyVisitor2();
            sub = new MySubject1();
            sub.accept(visitor);
    
            sub = new MySubject2();
            sub.accept(visitor);
        }
    }
    
  • 测试结果:
    visitor1 visits the subject1
    visitor1 visits the subject2
    visitor2 visit the subject1
    visitor2 visit the subject2
    

CLOS:

  • 使用generic函数,无须定义Vistor数据结构:
    ;; 数据结构
    (defclass subject ()
      ((name :accessor name))) 
    
    (defclass subject1 (subject)
      ((name :initform 'subject1)))
    
    (defclass subject2 (subject) 
      ((name :initform 'subject2)))
    
    ;; 不同的操作
    (defmethod op1 ((sub subject1))
      (format nil "visitor1 visits the ~A "
              (name sub))) 
    
    (defmethod op1 ((sub subject2))
      (format nil "visitor1 visits the ~A "
              (name sub)))
    
    (defmethod op2 ((sub subject1))
      (format nil "visitor2 visits the ~A "
              (name sub)))
    
    (defmethod op2 ((sub subject2))
      (format nil "visitor2 visits the ~A "
              (name sub)))
    
  • 测试结果:
    (op1 (make-instance 'subject1))
    ;; => "visitor1 visits the SUBJECT1 "
    (op1 (make-instance 'subject2))
    ;; => "visitor1 visits the SUBJECT2 "
    (op2 (make-instance 'subject1))
    ;; => "visitor2 visits the SUBJECT1 "
    (op2 (make-instance 'subject2)) 
    ;; => "visitor2 visits the SUBJECT2 "
    

Next:中介者模式

Previous:状态模式

Home:目录