广告位联系
返回顶部
分享到

Java访问者模式实现优雅的对象结构处理

java 来源:互联网 作者:佚名 发布时间:2023-11-22 22:25:42 人浏览
摘要

Java访问者模式(Visitor Pattern)是一种行为型设计模式,它允许将算法与其所操作的对象分离.该模式定义了一个访问者对象,它可以访问不同类型的对象并执行一些操作,同时也能让你在不修改

Java访问者模式(Visitor Pattern)是一种行为型设计模式,它允许将算法与其所操作的对象分离.该模式定义了一个访问者对象,它可以访问不同类型的对象并执行一些操作,同时也能让你在不修改现有代码的情况下,添加新的操作.

再访问者模式中,有两个重要的角色:访问者和元素. 元素是一个对象结构的组成部分.访问者是一个表示要执行的操作的对象.访问者可以通过元素的接受方法来访问元素.

Java访问者模式通常涉及以下5种角色:

  • 抽象访问者(Visitor):定义了可以访问每个元素的访问方法.
  • 具体访问者(Concrete Visitor):实现了抽象访问者定义的访问方法,包含针对不同元素的具体操作.
  • 抽象元素(Element):定义了一个接受访问者对象的方法,使访问者可以访问自己.
  • 具体元素(Concrete Element):实现了抽象元素定义的接受访问者方法,使访问者能够访问自己.
  • 对象结构(Object Structure):包含元素的集合,可以提供迭代器遍历元素,并且可以接受访问者的访问.

实现

动物园中有不同种类的动物,包括狗,猫和鸟.访问者模式可以用于统计不同类型的动物的个数,以及不同类型的动物的属性信息.

抽象元素

1

2

3

public interface Animal {

    void accept(Visitor visitor);

}

具体元素

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

@Data

public class Bird implements Animal{

    private String name;

    private String habitat;

    public Bird(String name, String habitat) {

        this.name = name;

        this.habitat = habitat;

    }

    @Override

    public void accept(Visitor visitor) {

        visitor.visitor(this);

    }

}

@Data

public class Cat implements Animal{

    private String sound;

    private int age;

    public Cat(String sound, int age) {

        this.sound = sound;

        this.age = age;

    }

    @Override

    public void accept(Visitor visitor) {

        visitor.visitor(this);

    }

}

@Data

public class Dog implements Animal{

    private String color;

    private int size;

    public Dog(String color, int size) {

        this.color = color;

        this.size = size;

    }

    @Override

    public void accept(Visitor visitor) {

        visitor.visitor(this);

    }

}

抽象访问者

1

2

3

4

5

public interface Visitor {

    void visitor(Dog dog);

    void visitor(Cat cat);

    void visitor(Bird bird);

}

具体访问者

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

public class AnimalCountVisitor implements Visitor{

    private int dogCount;

    private int birdCount;

    private int catCount;

    @Override

    public void visitor(Dog dog) {

        dogCount++;

    }

    @Override

    public void visitor(Cat cat) {

        catCount++;

    }

    @Override

    public void visitor(Bird bird) {

        birdCount++;

    }

    public void printCount(){

        System.out.println("狗的个数:"+dogCount);

        System.out.println("猫的个数:"+catCount);

        System.out.println("鸟的个数:"+birdCount);

    }

}

public class AnimalFeatureVisitor implements Visitor {

    private List<String> features;

    public AnimalFeatureVisitor() {

        features = new ArrayList<>();

    }

    @Override

    public void visitor(Dog dog) {

        features.add("Dog:color=" + dog.getColor() + ",size=" + dog.getSize());

    }

    @Override

    public void visitor(Cat cat) {

        features.add("Car:sound=" + cat.getSound() + ",age=" + cat.getAge());

    }

    @Override

    public void visitor(Bird bird) {

        features.add("Bird:name=" + bird.getName() + ",habitat=" + bird.getHabitat());

    }

    public void printFeatures(){

        features.forEach(System.out::println);

    }

}

测试

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class Demo {

    public static void main(String[] args) {

        List<Animal> animals = new ArrayList<>();

        animals.add(new Dog("褐色", 50));

        animals.add(new Dog("白色", 45));

        animals.add(new Cat("喵喵叫", 2));

        animals.add(new Cat("呜呜声", 3));

        animals.add(new Bird("鹦鹉", "森林"));

        animals.add(new Bird("麻雀", "田野"));

        AnimalCountVisitor animalCountVisitor = new AnimalCountVisitor();

        AnimalFeatureVisitor animalFeatureVisitor = new AnimalFeatureVisitor();

        animals.forEach(animal -> {

            animal.accept(animalCountVisitor);

            animal.accept(animalFeatureVisitor);

        });

        animalCountVisitor.printCount();

        animalFeatureVisitor.printFeatures();

    }

}

再这个例子中,我们定义了三种动物类,包括Dog,Cat和Bird,它们都实现了Animal接口,并且是心啊了accept方法,其中传入了Visitor类型的参数.

接下来,定义了Visitor接口,其中包含了visitor方法,该方法根据传入的不同类型的动物进行访问.

再具体的Visitor的实现中,定义了AnimalCountVisitor和AnimalFeatureVisitor两个访问者,前者用于统计不同类型的动物的个数,后者用于打印不同类型的动物的属性.

总结

优点

  • 分离算法与对象:访问者模式使得算法与对象分离成为可能,因为算法被定义在访问者中,而对象则在被访问时向访问者公开自己的数据.
  • 扩展性好:该模式可以方便地添加新的操作而不会影响现有的对象结构,因为访问者模式将对象结构与操作分离开来.
  • 符合开闭原则:访问者模式符合开闭原则,因为您可以在不更改现有代码的情况下添加新的访问者和新的元素类型.
  • 简化代码逻辑:访问者模式将对象和操作分离开来,简化了代码逻辑.

缺点

  • 增加新的元素类型困难:当需要增加新的元素类型时,必须修改现有的访问者接口,这可能导致对现有代码的修改.
  • 破坏封装:访问者模式需要将对象的内部数据暴漏给访问者,这可能破坏对象的封装性.

应用场景

  • 当需要对一个复杂对象结构进行操作而不想暴漏其内部实现时,可以使用访问者模式.
  • 当需要为对象结构中的各个对象增加一些新的操作而不影响其类层次结构时,可以使用访问者模式.
  • 当对象的类层次结构发生变化,但其操作仍然保持相对稳定时,可以使用访问者模式.
  • 当需要在运行时动态确定要执行的操作时,可以使用访问者模式.

版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 将maven源改为国内阿里云镜像的教程

    将maven源改为国内阿里云镜像的教程
    由于众所周知的原因,maven的库在中国大陆非常慢。我在百度上搜到的大部分文章都是直接在~/.m2/settings.xml 加入以下内容 1 2 3 4 5 6 7 8 mirro
  • Java访问者模式实现优雅的对象结构处理

    Java访问者模式实现优雅的对象结构处理
    Java访问者模式(Visitor Pattern)是一种行为型设计模式,它允许将算法与其所操作的对象分离.该模式定义了一个访问者对象,它可以访问不同类型
  • java之CSV大批量数据入库的实现方法

    java之CSV大批量数据入库的实现方法
    需求 读200+的CSV/EXCEL文件,按文件名称存到不同数据库 前期准备 环境 maven + jdk8 + mysql 代码展示 pom文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  • SpringBoot起步依赖和自动配置介绍

    SpringBoot起步依赖和自动配置介绍
    1、起步依赖 概念 起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起支持某
  • intellij idea自动生成类注释和方法注释配置方法

    intellij idea自动生成类注释和方法注释配置方法
    intellij idea自动生成类注释和方法注释 1.新建类,自动生成类注释的模板配置 File-Settings-Editor-File and Code Templates-Class 1 2 3 4 5 /** @Description: T
  • Java线程的停止实现原理介绍
    线程停止的原理 使用interrupt来通知,而不是强制 java提供了interrrupt让一个线程来通知另一个线程停止 如果想中断一个线程,但是那个线程不
  • springboot按月分表的实现方式介绍

    springboot按月分表的实现方式介绍
    在实际工作中,会遇到业务比较集中的情况,随着时间推延,这部分业务关联的mysql表就会越来越大,十分臃肿。尽管在项目架构上做了读写
  • jmap执行失败如何获取heapdump

    jmap执行失败如何获取heapdump
    在之前的OOM问题复盘中,我们添加了jmap脚本来自动dump内存现场,方便排查OOM问题。 但当我反复模拟OOM场景测试时,发现jmap有时可以dump成功
  • Spring refresh()源码解析介绍

    Spring refresh()源码解析介绍
    正文 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public void refresh() throws BeansException, IllegalStateExcept
  • 线程阻塞唤醒工具LockSupport使用介绍
    LockSupport 简介 LockSupport是 Java 并发编程中一个非常重要的组件,我们熟知的并发组件Lock、线程池、CountDownLatch等都是基于AQS实现的,而AQS内
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计