设计模式之访问者模式

写在前面

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

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)

相关推荐
政沅同学2 小时前
C# 一种很好用的设计模式 不同对象之间进行解耦通信
设计模式·c#
一颗青果2 小时前
工厂设计模式
设计模式
两年半的个人练习生^_^4 小时前
每日一学:设计模式之建造者模式
java·开发语言·设计模式
sg_knight15 小时前
设计模式实战:命令模式(Command)
python·设计模式·命令模式
渔舟小调21 小时前
P11 | 收藏与行程:用户行为类接口的设计模式
数据库·设计模式·oracle
小程故事多_801 天前
从基础Agent到复杂工作流,LangGraph如何用状态机重构智能体开发
人工智能·设计模式·重构·aigc·ai编程
hypoy1 天前
Claude Code 的 1M Context 怎么用:一篇官方文章的读后整理
设计模式·claude
IT 行者1 天前
软件设计模式会不会是制约大模型编程的障碍?
设计模式·ai编程
t***5441 天前
还有哪些设计模式适合现代C++
开发语言·c++·设计模式
t***5441 天前
如何在现代C++项目中有效应用这些设计模式
开发语言·c++·设计模式