设计模式-访问者模式(Visitor)

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/love905661433/article/details/84454106

概述

  • 定义 : 封装作用于某数据结构(如List/Set/Map等)中的各元素的操作
  • 可以在不改变各元素的类的前提下, 定义左用于这些元素的操作
  • 类型 : 行为型

适用场景

  • 一个数据结构(如List/Set/Map等)包含很多类型对象
  • 数据结构与数据操作分离

优点

  • 增加新的操作很容易, 即增加一个新的访问者

缺点

  • 增加新的数据结构困难
  • 具体元素变更比较麻烦

模式角色

  • Visitor(访问者) : 为该对象结构中C o n c r e t e E l e m e n t的每一个类声明一个 Vi s i t操作。该操作的名字和特征标识了发送Vi s i t请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。

  • ConcreteVisitor(具体访问者) : 实现每个由Vi s i t o r声明的操作。每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。

  • Element(元素) : 定义一个Accept操作,它以一个访问者为参数。

  • ConcreteElement(具体元素) : 实现Accept操作,该操作以一个访问者为参数。

  • ObjectStructure(对象结构) :

    • 能枚举它的元素
    • 可以提供一个高层的接口以允许该访问者访问它的元素
    • 可以是一个复合或是一个集合,如一个列表或一个无序集合

代码实现

场景

一个观察者, 访问两个Element,ConcreteElementA 和 ConcreteElementB, ConcreteElementA 只有name属性, 所以访问它是只展示name值, ConcreteElementB除了name之外, 还具有一个绰号nickname属性, 所以访问它要展示两个属性, 类命名方式和角色名保持一致

UML类图

在这里插入图片描述

代码

/**
 * Element(元素)角色
 * @author 七夜雪
 * @create 2018-11-24 21:36
 */
public interface Element {
    public void accept(Visitor visitor);
}
/**
 * ConcreteElement(具体元素) 
 * @author 七夜雪
 * @create 2018-11-24 21:36
 */
public class ConcreteElementA implements Element {
    private String name;

    public ConcreteElementA(String name) {
        this.name = name;
    }

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

    public String getName() {
        return name;
    }
}
/**
 * ConcreteElement(具体元素) 
 * @author 七夜雪
 * @create 2018-11-24 21:37
 */
public class ConcreteElementB implements Element {
    private String name;
    private String nickname;

    public ConcreteElementB(String name, String nickname) {
        this.name = name;
        this.nickname = nickname;
    }

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

    public String getName() {
        return name;
    }

    public String getNickname() {
        return nickname;
    }
}
/**
 * 访问者接口
 * Visitor(访问者)角色
 * @author 七夜雪
 * @create 2018-11-24 21:29
 */
public interface Visitor {
    public void visit(ConcreteElementA element);
    public void visit(ConcreteElementB element);
}
/**
 * ConcreteVisitor(具体访问者) 角色
 * @author 七夜雪
 * @create 2018-11-24 21:37
 */
public class ConcreteVisitor implements Visitor {

    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("访问者姓名 : " + element.getName());
    }

    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("访问者姓名 : " + element.getName() + ", 江湖人称 : " + element.getNickname());
    }
}

测试代码 :

/**
 * 测试类
 *
 * @author 七夜雪
 * @create 2018-11-24 21:48
 */
public class Client {
    public static void main(String[] args) {
	    // 这个List对应ObjectStructure(对象结构) 角色
        List<Element> elements = new ArrayList<>();
        Element elementA = new ConcreteElementA("七夜雪");
        Element elementB = new ConcreteElementB("杨过", "神雕大侠");
        elements.add(elementA);
        elements.add(elementB);
        for (Element element : elements) {
            element.accept(new ConcreteVisitor());
        }
    }

}

本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>

猜你喜欢

转载自blog.csdn.net/love905661433/article/details/84454106