设计模式 - 访问者模式

访问者模式:在数据结构与用户之间,提供一层visitor封装,用户通过visitor对数据结构进行访问(类似存储过程)
核心:visitor封装对数据结构的操作,用户通过visitor对数据结构进行访问(每一个visitor实现子类都对应了一种访问方式)
角色:

  • IVisitor: 提供访问元素的抽象接口 - 需提供所有ConcreteElement对象的visit访问方法

  • ConcreteVisitor: IVisitor的实现子类,其内定义针对每一种ConcreteElement的具体操作(访问方式)

  • IElement/ConcreteElement: 元素,可能存在IElement的多种实现。

  • ObjectStructure: 数据结构(数据表),维护所有的IElement实例,并提供接受IVisitor,以遍历访问所有的element。

PS: ①由ObjectStructure维护所有Element的集合,②用户需通过IVisitor实现对ObjectStructure中元素的访问

general

IVisitor

// IVisitor接口中需定义对所有类型元素的访问方法
public interface IVisitor {
    void visit(ElementA element);
    void visit(ElementB element);
}

// 每一个Visitor都代表一种对数据集合的访问模式。
public class Visitor1 implements IVisitor{
    public void visit(ElementA element) { System.out.println(element.getId() + " - core:" + element.getCore() );}
    public void visit(ElementB element) { System.out.println(element.getId() + " - spend:" + element.getSpend() );}
}

ObjectStructure

// 数据集合,维护数据集合相关的操作,以及提供一个为visitor访问所有element的方法
public class ElementContainer {
    private ArrayList<IElement> elements = new ArrayList<>();

    public void addElement(IElement element){ ... }

    // 使所有的element接受visitor的访问
    public void show(IVisitor visitor){
        for(IElement element : elements){
            element.accept(visitor);
        }
    }
}

IElement

// IElement接口中声明接受IVisitor访问的方法
public interface IElement {
    void accept(IVisitor visitor);
}

//  IElement实现子类,在编译时,根据方法重载可确定调用IElement的哪个方法,在运行时,根据继承链找到具体的子类实现方法。
public class ElementA implements IElement{
    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

方法重写与重载

public class Dispatch {
    public static void main(String[] args) {
        // 方法重载,静态分派 -- 编译阶段即可确定调用方法
        Dispatch dispatch = new Dispatch();
        dispatch.print(100);
        dispatch.print("100");

        // 方法重写,动态分派 -- 只有运行过程中根据对象的实际类型确定调用方法
        IPerson person = dispatch.createPerson();
        person.getSex();                              // may: Woman.getSex() or Man.getSex()
    }

    private void print(String str){
        System.out.println("Str is " + str);
    };

    private void print(Integer i){
        System.out.println("Num is " + i);
    }
}
posted @ 2020-12-08 15:44  祁奇  阅读(48)  评论(0编辑  收藏  举报