设计模式之访问者模式

写在前面

本文看一种行为型设计模式,访问者模式。

1:介绍

1.1:什么时候使用访问者设计模式

当一个对象(objectstructure),有固定的的几个元素(element),并且当这个对象要完成不同的任务(Visitor)时,固定的这几个元素在任务中承担的职责也不同,当满足这种场景时就可以考虑使用访问者设计模式。

1.2:UML类图

原型设计模式,包含如下元素:

复制代码
1:objectstructure
    拥有固定元素个数的对象
2:Element
    objectstructure中的元素,定义了accept(visitor)方法把自己交给访问者访问
3:ConcreteElement
    具体元素类
3:Visitor
    访问者,其实就是对象要完成的具体任务

2:实例

源码

2.1:场景

王老板,开了一个公司,只有一个开发小草莓,一个测试小葡萄,一个hr小酸梅,王老板为了省钱,只有这三个员工,并且王老板开了两个业务线,分别做对标抖音的短视频APP和对标微信的聊天APP,开发小草莓,测试小葡萄,hr小酸梅,在不同的产品中承担了不同的角色。此场景和访问者设计模式元素的对应关系如下:

复制代码
Element:开发小草莓,测试小葡萄,hr小酸梅
objectstructure:王老板的公司,有三个element,开发小草莓,测试小葡萄,hr小酸梅
Visitor:短视频APP,微信的聊天APP

2.2:程序

  • 定义ELement
java 复制代码
public interface CorporateSlaveElement {
    // 接受不同访问者的访问(相当于是接受不同的任务,并在任务中承担不同的角色)
    void accept(CorporateSlaveVisitor visitor);
}
  • ConcreteElement
    hr小酸梅:
java 复制代码
public class HumanSourceElement implements CorporateSlaveElement {

    private String name;

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

    public String getName() {
        return name;
    }

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

开发小草莓:

java 复制代码
public class ProgrammerElement implements CorporateSlaveElement {
    private String name;

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

    public String getName() {
        return name;
    }

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

测试小葡萄:

java 复制代码
public class TesterElement implements CorporateSlaveElement {

    private String name;

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

    public String getName() {
        return name;
    }

    @Override
    public void accept(CorporateSlaveVisitor visitor) {
        visitor.visit(this);
    }
}
  • 定义visitor
java 复制代码
public interface CorporateSlaveVisitor {
    void visit(ProgrammerElement programmer);

    void visit(HumanSourceElement humanSource);

    void visit(TesterElement tester);
}

即让不同的任务能够访问Element,并使用其在自己的任务中完成特定的任务。接下定义具体访问者,对标抖音的短视频APP和对标微信的聊天APP:

java 复制代码
public class LiveAppVisitor implements CorporateSlaveVisitor {
    @Override
    public void visit(ProgrammerElement programmer) {
        System.out.println(programmer.getName() + " 在短视频中发挥作用了");
    }

    @Override
    public void visit(HumanSourceElement humanSource) {
        System.out.println(humanSource.getName() + " 在短视频中发挥作用了");
    }

    @Override
    public void visit(TesterElement tester) {
        System.out.println(tester.getName() + " 在短视频中发挥作用了");
    }
}

public class SocialAppVisitor implements CorporateSlaveVisitor {
    @Override
    public void visit(ProgrammerElement programmer) {
        System.out.println(programmer.getName() + " 在社交应用中发挥作用了");
    }

    @Override
    public void visit(HumanSourceElement humanSource) {
        System.out.println(humanSource.getName() + " 在社交应用中发挥作用了");
    }

    @Override
    public void visit(TesterElement tester) {
        System.out.println(tester.getName() + " 在社交应用中发挥作用了");
    }
}
  • objectstructure
    即王老板的公司,拥有一个开发小草莓,一个测试小葡萄,一个hr小酸梅,三个元素:
java 复制代码
public class BigHuYouCompany {
    private static List<CorporateSlaveElement> employee = new ArrayList() {
        {
            add(new ProgrammerElement("开发小草莓"));
            add(new HumanSourceElement("hr小酸梅"));
            add(new TesterElement("测试小葡萄"));
        }
    };
    private CorporateSlaveVisitor visitor;
//    public BigHuYouCompany() {
//        employee.add(new ProgrammerElement("开发小草莓"));
//        employee.add(new HumanSourceElement("hr小酸梅"));
//        employee.add(new TesterElement("测试小葡萄"));
//    }

    public BigHuYouCompany(CorporateSlaveVisitor visitor) {
        this.visitor = visitor;
    }

//    public void startProject(CorporateSlaveVisitor visitor){
    public void startProject(){
        for (CorporateSlaveElement slave : employee) {
            slave.accept(visitor);
        }
    }
}
  • 客户端类
java 复制代码
 @Test
public void startProject() {
    System.out.println("-----------------启动社交APP项目--------------------");
    BigHuYouCompany bigHuYouDoSocialApp= new BigHuYouCompany(new SocialAppVisitor());
    //可以很轻松的更换Visitor,但是要求BigHuYouCompany的结构稳定
    bigHuYouDoSocialApp.startProject();
    System.out.println("-----------------启动短视频APP项目--------------------");
    BigHuYouCompany liveAppVisitor= new BigHuYouCompany(new LiveAppVisitor());
    liveAppVisitor.startProject();
}

运行:

复制代码
-----------------启动社交APP项目--------------------
开发小草莓 在社交应用中发挥作用了
hr小酸梅 在社交应用中发挥作用了
测试小葡萄 在社交应用中发挥作用了
-----------------启动短视频APP项目--------------------
开发小草莓 在短视频中发挥作用了
hr小酸梅 在短视频中发挥作用了
测试小葡萄 在短视频中发挥作用了

Process finished with exit code 0

写在后面

参考文章列表

秒懂设计模式之访问者模式(Visitor Pattern)

相关推荐
willow3 天前
Axios由浅入深
设计模式·axios
七月丶5 天前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞5 天前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
九狼5 天前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
静水流深_沧海一粟5 天前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder5 天前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室6 天前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦7 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding
阿闽ooo10 天前
中介者模式打造多人聊天室系统
c++·设计模式·中介者模式