二十三種設計模式-訪問者模式

訪問者模式(Visitor)

在現實世界中,訪問者又叫做拜訪者。客人到主人家做客,客人就是一個拜訪者。對主人來說,你來與不來,我都在那裏。

什麼是訪問者模式

訪問者是一種行爲型模式,主要是對象自身的結構和對象的具體行爲相分離,通過一個對象維護對象自身的結構(這個結構不能是易變的,否則這種模式就沒太大的意義了),通過另一個對象(就是我們說的訪問者)維護施加在對象結構上的行爲。

通過將對象的結構和行爲進行相分離,可以讓對象的行爲獨立變化,當需要增加新的行爲時,只需要改變訪問者即可,而對象的結構是不需要變化的。

基本結構

結構圖

Node表示對象結構的抽象定義;

Visitor表示訪問者,即對象的行爲定義在此對象內;

DataStructure表示有多個對象組成的數據結構對象,相當於對象的容器;

使用場景

  • 對象的結構是不易變的,但是對象的行爲是易變的,此時就可以將對象的結構和行爲進行解耦操作;

優點

  • 好的擴展性
  • 好的複用性
  • 分離無關行爲

缺點

  • 對象結構變化很困難
  • 破壞了封裝性

使用案例

Demo

import java.util.ArrayList;
import java.util.List;

/**
 *
 * 訪問者模式:行爲型模式
 *
 * 基本構件:
 * (1)抽象訪問者:聲明訪問者可以訪問哪些元素
 * (2)具體訪問者:實現抽象訪問者中聲明的方法
 * (3)抽象元素類:聲明接收哪一類訪問者訪問;同時還包含自己的一些業務邏輯
 * (4)具體元素類:實現抽象元素類所聲明的accept方法
 * (5)結構對象:一個元素的容器
 *
 * 適用場景:防止一些不相干的操作干擾元素本身,可以將這些不相干的操作提到訪問者中。
 * 如果一個對象結構非常複雜,同時結構不易變化,但需要經常定義基於此結構上的新操作,則
 * 非常適用於訪問者模式。比如:複雜的集合對象、XML文檔解析、編譯器的設計等。
 *
 * 注:核心是結構不易變,而定義在上的操作易變;
 * 行爲是在訪問者中實現的,元素中主要是保存結構信息。
 *
 * 比如一份靜態數據,相當於結構不易變的,但是呢,經常需要變換指標來衡量一個標準,則可以
 * 採用訪問者模式
 *
 *
 */
public class VisitorBase {

    public static void main(String[] args) {
        Element element = new Student("s1", 91, 3);
        Element element1 = new Student("s2", 98, 3);
        Element element2 = new Teacher("t1", 101, 10);
        Element element3 = new Teacher("t2", 103, 20);
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(element)
                .addElement(element1).addElement(element2).addElement(element3);
        ReseacrcherVisitor visitor = new ReseacrcherVisitor();
        objectStructure.accept(visitor);
        System.out.println("select another");
        ScoreVisitor visitor1 = new ScoreVisitor();
        objectStructure.accept(visitor1);
    }

    static class ObjectStructure {
        List<Element> elements = new ArrayList<>();

        public void accept(IVisitor visitor) {
            for(Element element : elements) {
                element.accept(visitor);
            }
        }

        public ObjectStructure addElement(Element element) {
            elements.add(element);
            return this;
        }

        public ObjectStructure removeElement(Element element) {
            elements.remove(element);
            return this;
        }
    }

    static interface IVisitor {
        void visit(Teacher teacher);

        void visit(Student student);
    }

    static class ReseacrcherVisitor implements IVisitor {
        @Override
        public void visit(Teacher teacher) {
            if(teacher.paperCount > 6) {
                System.out.println("老師論文數達到了6篇,入選優秀工作者");
            }
        }

        @Override
        public void visit(Student student) {
            if(student.paperCount > 2) {
                System.out.println("學生論文數達到了2篇,入選優秀工作者");
            }
        }
    }

    static class ScoreVisitor implements IVisitor {
        @Override
        public void visit(Teacher teacher) {
            if(teacher.score > 100) {
                System.out.println("老師分數達到了100,入選優秀工作者");
            }
        }

        @Override
        public void visit(Student student) {
            if(student.score > 90) {
                System.out.println("學生分數達到了90,入選優秀工作者");
            }
        }
    }

    static interface Element {
        void accept(IVisitor visitor);
    }

    static class Teacher implements Element {

        private String name;

        private int score;

        private int paperCount;

        public Teacher(String name, int score, int paperCount) {
            this.name = name;
            this.score = score;
            this.paperCount = paperCount;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getScore() {
            return score;
        }

        public void setScore(int score) {
            this.score = score;
        }

        public int getPaperCount() {
            return paperCount;
        }

        public void setPaperCount(int paperCount) {
            this.paperCount = paperCount;
        }

        @Override
        public void accept(IVisitor visitor) {
            visitor.visit(this);
        }
    }

    static class Student implements Element {

        private String name;

        private int score;

        private int paperCount;

        public Student(String name, int score, int paperCount) {
            this.name = name;
            this.score = score;
            this.paperCount = paperCount;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getScore() {
            return score;
        }

        public void setScore(int score) {
            this.score = score;
        }

        public int getPaperCount() {
            return paperCount;
        }

        public void setPaperCount(int paperCount) {
            this.paperCount = paperCount;
        }

        @Override
        public void accept(IVisitor visitor) {
            visitor.visit(this);
        }
    }
}

Spring的案例

public abstract class AnnotationVisitor {
}

public abstract class ClassVisitor {
}

public abstract class FieldVisitor {
}

public abstract class MethodVisitor {
}

public abstract class ModuleVisitor {
}

大家搜索spring源碼會發現這些抽象類,用於訪問註解、類、成員變量等。在Visitor中定義操作這些對象的一些操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章