设计模式-访问者模式

设计模式-访问者模式

访问者者模式的英文翻译是 Visitor Design Pattern。它是这么定义的:Allows for one or more operation to be applied to a set of objects at runtime, decoupling the operations from the object structure. 翻译成中文就是:允许一个或者多个操作应用到一组对象上,解耦操作和对象本身。

案例分析

如果有一个接口,这个接口有三个实现类,那么我们可以充分利用多态特性进行处理

java 复制代码
public interface Visit {

    void visit();

}

public class AVisitor implements Visit {

    @Override
    public void visit() {
        System.out.println("AVisitor:visit");
    }

}

public class BVisitor implements Visit {

    @Override
    public void visit() {
        System.out.println("BVisitor:visit");
    }
    
}

public class CVisitor implements Visit {
    @Override
    public void visit() {
        System.out.println("CVisitor:visit");
    }

}

由于这三个实现类都实现了该接口,因此可以借助多态特性使用

java 复制代码
public class Main {

    public static void main(String[] args) {
        List<String> types = List.of("A","B","C");
        String type = types.get(new Random().nextInt(3));
        Visit visit = new AVisitor();
        if (type.equals("A")) {
            visit = new AVisitor();
        }
        if (type.equals("B")) {
            visit = new BVisitor();
        }
        if (type.equals("C")) {
            visit = new CVisitor();
        }
        processVisit(visit);
    }

    private static void processVisit(Visit visit) {
        visit.visit();
    }

}

这也是我们经常用到的方式

但是随着接口的方法增加,所有的实现类都需要新增实现接口的内容,如果接口的内容过多,会导致实现类的内容非常庞大,那么我们可以反向思考,按照功能实现接口,还是如上的场景,例如 ABC 三个实现类都需要实现接口中的 funcation1 和 funcation2 方法,我们定义如下接口

java 复制代码
public interface Visit {

    void visit(AFuncationImpl a);

    void visit(BFuncationImpl b);

    void visit(CFuncationImpl c);

}

利用接口重载支持多个实现类,接着我们按照功能拆分为 funcation1 类 和 funcation2 类

java 复制代码
public class Funcation1Visitor implements Visit {

    @Override
    public void visit(AFuncationImpl a) {
        System.out.println("AVisitor Funcation1");
    }

    @Override
    public void visit(BFuncationImpl b) {
        System.out.println("BVisitor Funcation1");
    }

    @Override
    public void visit(CFuncationImpl c) {
        System.out.println("CVisitor Funcation1");
    }

}

public class Funcation2Visitor implements Visit {

    @Override
    public void visit(AFuncationImpl a) {
        System.out.println("AVisitor Funcation2");
    }

    @Override
    public void visit(BFuncationImpl b) {
        System.out.println("BVisitor Funcation2");
    }

    @Override
    public void visit(CFuncationImpl c) {
        System.out.println("CVisitor Funcation2");
    }

}

经过这样的拆分,可以看出每个 Funcation 中一般只有实现类个方法。

那么该如何使用呢,每一个 FuncationVisitor 的参数已经变成具体的实现类类,是不是就无法充分利用多态特性了?

我们可以再定义一个接口

java 复制代码
public interface Accept {

    void accept(Visit visit);

}

所有的 CFuncationImpl 实现这个接口,并传入具体的 FuncationVisitor,这样就能充分利用多态特性了

java 复制代码
public class AFuncationImpl implements Accept {

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

}

public class BFuncationImpl implements Accept {

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

}

public class CFuncationImpl implements Accept {

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

}

测试代码:

java 复制代码
public class Main {

    public static void main(String[] args) {
        List<Accept> acceptList = List.of(new AFuncationImpl(), new BFuncationImpl(), new CFuncationImpl());

        Visit visit = new Funcation1Visitor();
        for (Accept accept : acceptList) {
            accept.accept(visit);
        }

        visit = new Funcation2Visitor();
        for (Accept accept : acceptList) {
            accept.accept(visit);
        }
    }

}

类之间关系如图:

梳理一下改动的思路,由于接口中的方法越来越多会导致实现类的代码越来越多,访问者模式提供了一种思路按照功能进行抽象(Visit),利用接口重载为所有的实现类设置一个方法(Visit.visit),并让所有的功能类实现这个方法。

由于功能类实现后正常情况下无法利用多态特性(此时的参数是具体实现类),因此可以让具体实现类(AFuncationImpl、BFuncationImpl等)实现一个统一的接口(Accept)。

访问者模式为了避免不断添加功能导致类不断膨胀,职责越来越不单一,以及避免频繁地添加功能导致的频繁代码修改,将对象与操作解耦,将这些业务操作抽离出来,定义在独立细分的访问者类中。

相关推荐
艺艺生辉16 小时前
从if-else到策略模式
后端·设计模式
小林ixn16 小时前
单例模式:从弹窗管理到全局状态,一个模式搞定
前端·javascript·设计模式
AI人工智能+电脑小能手18 小时前
大白话说Java设计模式-17-装饰器模式(源码剖析篇)
java·spring·设计模式·装饰器模式·源码分析·io流
workflower19 小时前
案例 :某交通厅基于AI技术的智能安全运营实践
网络·人工智能·安全·设计模式·机器人
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-16-装饰器模式(业务实战篇)
java·设计模式·装饰器模式·功能扩展·动态增强
workflower2 天前
例二:某汽车制造企业深度融合AI智能体,构建园区网络的智能运维体系
人工智能·机器学习·设计模式·机器人·云计算·汽车·制造
ly76892 天前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
AI人工智能+电脑小能手2 天前
大白话说Java设计模式-14-适配器模式(业务实战篇)
java·设计模式·适配器模式·系统兼容·多渠道对接
略略略咯咯2 天前
(总结)设计模式
设计模式
Cosolar3 天前
DeepSeek Harness 理解 Harness 的设计哲学 - 可组合的插件运行时
人工智能·设计模式·架构