设计模式 – 访问者模式

导读:本篇文章讲解 设计模式 – 访问者模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

访问者模式(Visitor Pattern)

一. 概念

通俗易懂的解释:同一个事物,不同视角下访问的内容各不相同

wiki解释:在面向对象编程和软件工程中,访问者设计模式是一种将算法从其操作的对象结构中分离出来。这是一个实际的结果分离是向现有对象结构添加新操作而无需修改的能力的结构。

二. 解决的问题

稳定的数据结构和易变的操作耦合问题,就是把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化

三. 使用场合

  1. 对象结构包含许多不同接口的实现类,您希望对这些对象执行依赖于其具体类的操作
  2. 在对象结构中,需要对对象执行许多不同的和不相关的操作

jdk源码中的使用

四. 实现

4.1 访问者模式结构图

请添加图片描述

4.2 实现核心-双分派

双分派:调用哪个对象的方法,在运行期(多态)确定;调用对象的哪个方法(方法重载),在运行期确定。

五. 小试牛刀

5.1 例子

军队的等级,大家肯定耳濡目染,在我的印象中,军队等级制度=树状结构。

不同的等级,访问的信息角度维度也大不相同

遇见指挥官,我们会说:很开心遇见你,指挥官

遇见军士,我们会说:欢迎你,军士

遇见士兵,我偶们会说:哈喽,士兵

遇见不同的对象,我们的说话信息都是大不相同,那么我们就已这个角度来实现访问者把

指挥官

军士1

军士2

士兵1

士兵2

士兵3

士兵4

士兵5

士兵6


5.2 UML图

请添加图片描述

5.3 代码实现

⭐️依赖

 	    <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.7.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

⭐️Unit – 军队基类

/**
 * @author zhanghp
 * @date 2022-08-10 10:03
 */
public abstract class Unit {

    private final Unit[] CHILD_ARRAYS;

    public Unit(Unit ... unit){
        this.CHILD_ARRAYS = unit;
    }

    public void accept(UnitVisitor visitor){
        Arrays.stream(CHILD_ARRAYS).forEach(child -> child.accept(visitor));
    }
}

⭐️Commander – 指挥官

/**
 * 指挥官
 *
 * @author zhanghp
 * @date 2022-08-10 9:59
 */
public class Commander extends Unit{
    public Commander(Unit... unit) {
        super(unit);
    }

    @Override
    public String toString() {
        return "commander";
    }

    @Override
    public void accept(UnitVisitor visitor) {
        // 鉴别观察者
        if(visitor instanceof CommanderVisitor){
            visitor.visit(this);
        }
        super.accept(visitor);
    }
}

⭐️Sergeant – 军士

/**
 * @author zhanghp
 * @date 2022-08-10 10:11
 */
public class Sergeant extends Unit {

    public Sergeant(Unit... unit) {
        super(unit);
    }

    @Override
    public String toString() {
        return "sergeant";
    }

    @Override
    public void accept(UnitVisitor visitor) {
        // 鉴别观察者
        if(visitor instanceof SergeantVisitor){
            visitor.visit(this);
        }
        super.accept(visitor);
    }
}

⭐️Solider – 士兵

/**
 * @author zhanghp
 * @date 2022-08-10 10:16
 */
public class Solider extends Unit {
    public Solider(Unit... unit) {
        super(unit);
    }

    @Override
    public String toString() {
        return "solider";
    }

    @Override
    public void accept(UnitVisitor visitor) {
        // 鉴别观察者
        if(visitor instanceof SoliderVisitor){
            visitor.visit(this);
        }
        super.accept(visitor);
    }
}

⭐️UnitVIsitor – 军队访问基类

/**
 * @author zhanghp
 * @date 2022-08-10 10:23
 */
public interface UnitVisitor {
    void visit(Unit visitor);
}

⭐️CommanderVisitor – 指挥官访问者

/**
 * @author zhanghp
 * @date 2022-08-10 10:24
 */
@Slf4j
public class CommanderVisitor implements UnitVisitor{
    @Override
    public void visit(Unit commander) {
        log.info("Good to See you {}", commander);
    }
}

⭐️SergeantVisitor – 军士访问者

/**
 * @author zhanghp
 * @date 2022-08-10 10:28
 */
@Slf4j
public class SergeantVisitor implements UnitVisitor{
    @Override
    public void visit(Unit sergeant) {
        log.info("Greetings {}", sergeant);
    }
}

⭐️SoliderVisitor – 士兵访问者

/**
 * @author zhanghp
 * @date 2022-08-10 10:28
 */
@Slf4j
public class SoliderVisitor implements UnitVisitor {
    @Override
    public void visit(Unit solider) {
        log.info("Hello {}", solider);

    }
}

六. UT测试用例

6.1 代码

/**
 * @author zhanghp
 * @date 2022-08-10 10:49
 */
public class VisitorTest {
    @Test
    void visit(){
        Commander commander = new Commander(
                new Sergeant(new Solider(), new Solider(), new Solider()),
                new Sergeant(new Solider(), new Solider(), new Solider()));
        commander.accept(new CommanderVisitor());
        commander.accept(new SergeantVisitor());
        commander.accept(new SoliderVisitor());
    }
}

6.2 打印结果

[main] INFO com.zhanghp.demo01.visitor.CommanderVisitor - Good to See you commander
[main] INFO com.zhanghp.demo01.visitor.SergeantVisitor - Greetings sergeant
[main] INFO com.zhanghp.demo01.visitor.SergeantVisitor - Greetings sergeant
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider
[main] INFO com.zhanghp.demo01.visitor.SoliderVisitor - Hello solider

七. 参考资料及源码地址

iluwatarhttps://github.com/iluwatar/java-design-patterns/blob/master/visitor/README.md

双分派与访问者https://blog.csdn.net/qq_33905217/article/details/122400997

重构大师https://refactoringguru.cn/design-patterns/visitor


📌源码https://gitee.com/zhp1221/design_pattern/tree/master/lab_02_visitor

demo01本文章的练习源码
demo02:额外练习的例子
demo03:静态分派练习和Java源码FileVisitor的练习


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/63259.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!