设计模式之访问者模式

写在前面

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

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)

相关推荐
华仔啊3 小时前
别学23种了!Java项目中最常用的6个设计模式,附案例
java·后端·设计模式
Keya7 小时前
MacOS端口被占用的解决方法
前端·后端·设计模式
已读不回1437 小时前
设计模式-单例模式
前端·设计模式
long3161 天前
构建者设计模式 Builder
java·后端·学习·设计模式
一乐小哥1 天前
从 JDK 到 Spring,单例模式在源码中的实战用法
后端·设计模式
付春员1 天前
23种设计模式
设计模式
Zyy~2 天前
《设计模式》工厂方法模式
设计模式·工厂方法模式
ikkkkkkkl2 天前
C++设计模式:面向对象设计原则
c++·设计模式·面向对象
whitepure2 天前
万字详解Java中的面向对象(二)——设计模式
java·设计模式
稚辉君.MCA_P8_Java2 天前
豆包 Java的23种设计模式
java·linux·jvm·设计模式·kubernetes