大聪明教你学Java设计模式 | 第十九篇:访问者模式

241 阅读4分钟

前言

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情

🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。

🍊支持作者: 点赞👍、关注💖、留言💌~

大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案。大聪明本着“独乐乐不如众乐乐”的宗旨与大家分享一下设计模式的学习心得。

访问者模式

🍓🍓什么是访问者模式🍓🍓

在讲访问者模式之前,我们先来看一下它的定义👇

访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它属于行为型模式,并且是行为类模式中最复杂的一种模式。

访问者模式,它的重点就在“访问”二字,看到这两个字后可能我们脑海中肯定会出现新闻访谈的场景。同一个记者采访了不同的人,记者给每个人提出了若干个同样的问题,或许每个人的回答都不尽相同,每个人都给记者讲述了属于自己的故事。那么我们把这个例子再带回到访问者模式的定义中,记者采访的人物就是被处理的数据元素;而记者提出的问题就是多种多样的访问方式。那么当我们在开发应用程序时,如果遇到了类似于这种例子的场景,我们就可以采用访问者模式来解决此类问题。访问者模式能把处理方法从数据结构中分离出来(也就是将记者提出的问题和采访对象本身进行拆分),并可以根据需要增加新的处理方法(即可以随意改变需要提出的问题),且不用修改原来的程序代码与数据结构,这提高了程序的扩展性和灵活性。

其实类似这样的例子还有很多,例如,电影或电视剧中的人物角色,不同的观众对他们的评价也不同;一个完整的电脑包含了若干零件,如键盘、鼠标等,我们可以通过不同的零件完成不同的操作等等。所以说,只要我们有一双善于发现的眼睛,我们就能在现实生活中发现设计模式的影子。

🍓🍓访问者模式的实现🍓🍓

接下来我们就用电脑零件的例子来简单实现一下访问者模式👇

🍎🍎电脑零件接口类🍎🍎

/**
 * 电脑零件接口类
 * @description: ComputerPart
 * @author: 庄霸.liziye
 * @create: 2022-04-20 15:55
 **/
public interface ComputerPart {

    public void accept(ComputerPartVisitor computerPartVisitor);
}

🍎🍎实现电脑零件接口🍎🍎

/**
 * 实现电脑零件接口
 * @description: Keyboard
 * @author: 庄霸.liziye
 * @create: 2022-04-20 15:56
 **/
class Keyboard implements ComputerPart {

    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}

class Mouse implements ComputerPart {

    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}

class Monitor implements ComputerPart {

    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}

class Computer implements ComputerPart {

    ComputerPart[] parts;

    public Computer(){
        parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
    }


    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        for (int i = 0; i < parts.length; i++) {
            parts[i].accept(computerPartVisitor);
        }
        computerPartVisitor.visit(this);
    }
}

🍎🍎定义访问者接口🍎🍎

/**
 * 访问者接口
 * @description: ComputerPartVisitor
 * @author: 庄霸.liziye
 * @create: 2022-04-20 15:58
 **/
public interface ComputerPartVisitor {

    /**
     * 访问电脑
     * @param computer
     */
    public void visit(Computer computer);

    /**
     * 访问鼠标
     * @param mouse
     */
    public void visit(Mouse mouse);

    /**
     * 访问键盘
     * @param keyboard
     */
    public void visit(Keyboard keyboard);

    /**
     * 访问显示器
     * @param monitor
     */
    public void visit(Monitor monitor);
}

🍎🍎实现访问者接口🍎🍎

/**
 * 实现访问者接口
 * @description: ComputerPartDisplayVisitor
 * @author: 庄霸.liziye
 * @create: 2022-04-20 15:59
 **/
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {

    @Override
    public void visit(Computer computer) {
        System.out.println("我是电脑~");
    }

    @Override
    public void visit(Mouse mouse) {
        System.out.println("我是鼠标~");
    }

    @Override
    public void visit(Keyboard keyboard) {
        System.out.println("我是键盘~");
    }

    @Override
    public void visit(Monitor monitor) {
        System.out.println("我是显示器~");
    }
}

🍎🍎接下来看看电脑的组成部分🍎🍎

/**
 * @description: Test
 * @author: 庄霸.liziye
 * @create: 2022-04-11 11:31
 **/
public class Test {

    public static void main(String[] args) {

        ComputerPart computer = new Computer();
        computer.accept(new ComputerPartDisplayVisitor());
    }
}

🍎🍎运行结果🍎🍎

在这里插入图片描述

🍓🍓访问者模式的优、缺点🍓🍓

最后我们总结一下访问者模式的优点与缺点👇

🍌🍌优点🍌🍌

🍋 访问者模式能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能,可以让代码有更高的扩展性和灵活性;它把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一,完美的遵循了单一职责原则。

🍌🍌缺点🍌🍌

🥝 在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”,也增加了添加元素的难度;实现访问者模式的时候依赖了具体类,而没有依赖抽象类,这也违反了依赖倒置原则。

小结

本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇‍

希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)

如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。

爱你所爱 行你所行 听从你心 无问东西