当前位置: 首页 > news >正文

Java设计模式之访问者模式

概念

访问者模式是一种行为设计模式,允许在不修改已有代码的情况下,动态地添加新的操作到对象结构中。它将数据结构与操作解耦,使得可以独立地定义作用于复杂对象结构的操作。

作用

访问者模式的主要作用是解决在一个对象结构上定义多个操作的问题,特别是这些操作需要频繁改变时。它使得可以在不修改对象结构的前提下,方便地添加新的操作,符合单一职责原则和开闭原则。

使用场景

1.一个对象结构包含很多类对象,它们有不同的接口,而想对这些对象实施一些依赖于其具体类的操作。

2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类。

3.对象结构中的对象类型很少改变,但经常需要在此对象结构上定义新的操作。

实现

访问者模式的实现通常包括以下几个部分:

1.Visitor(访问者接口):声明了访问者可以访问哪些元素,通过为每种元素类声明一个访问操作(visit())来实现。

2.ConcreteVisitor(具体访问者):实现了Visitor接口中的访问操作,定义了对元素的具体访问行为。

3.Element(元素接口):声明了一个accept()方法,用于接受访问者访问。

4.ConcreteElement(具体元素):实现了Element接口中的accept()方法,通常会调用访问者的相应访问方法。

5.ObjectStructure(对象结构):是一个包含元素的容器,提供了遍历元素的方法,让访问者可以访问所有元素。

示例

1.访问者接口


// 访问者接口
interface ComputerPartVisitor {
    void visit(Mouse mouse);
    void visit(Keyboard keyboard);
    void visit(Display display);
    void visit(Computer computer);
}

2.具体访问者-清洁访问者

// 具体访问者 - 清洁访问者
class CleanVisitor implements ComputerPartVisitor {
    @Override
    public void visit(Mouse mouse) {
        System.out.println("清洁鼠标");
    }

    @Override
    public void visit(Keyboard keyboard) {
        System.out.println("清洁键盘");
    }

    @Override
    public void visit(Display display) {
        System.out.println("清洁显示器");
    }

    @Override
    public void visit(Computer computer) {
        System.out.println("清洁电脑");
    }
}

3.具体访问者-升级访问者

// 具体访问者 - 升级访问者
class UpgradeVisitor implements ComputerPartVisitor {
    @Override
    public void visit(Mouse mouse) {
        System.out.println("升级鼠标驱动");
    }

    @Override
    public void visit(Keyboard keyboard) {
        System.out.println("升级键盘驱动");
    }

    @Override
    public void visit(Display display) {
        System.out.println("升级显示器驱动");
    }

    @Override
    public void visit(Computer computer) {
        System.out.println("升级电脑系统");
    }
}

4.元素接口

// 元素接口
interface ComputerPart {
    void accept(ComputerPartVisitor visitor);
}

5.具体元素

// 具体元素 - 鼠标
class Mouse implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素 - 键盘
class Keyboard implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素 - 显示器
class Monitor implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor visitor) {
        visitor.visit(this);
    }
}
// 具体元素 - 电脑
class Computer implements ComputerPart {
    private List<ComputerPart> parts;

    public Computer() {
        parts = new ArrayList<>();
        parts.add(new Mouse());
        parts.add(new Keyboard());
        parts.add(new Monitor());
    }

    @Override
    public void accept(ComputerPartVisitor visitor) {
        for (ComputerPart part : parts) {
            part.accept(visitor);
        }
        visitor.visit(this);
    }
}

6.测试类

// 使用示例
public class VisitorPatternDemo {
    public static void main(String[] args) {
        Computer computer = new Computer();

        ComputerPartVisitor cleanVisitor = new CleanVisitor();
        computer.accept(cleanVisitor);

        ComputerPartVisitor upgradeVisitor = new UpgradeVisitor();
        computer.accept(upgradeVisitor);
    }
}

优缺点

优点

1.单一职责原则:将相关的行为集中在一个访问者类中,而不是分散在许多被访问的类中。

2.开闭原则:在不修改已有代码的情况下,可以方便地添加新的访问者类,从而定义新的操作。

3.复用性:访问者可以复用元素类中的方法,而不需要重新实现这些方法。

缺点

1.类的依赖性:访问者和元素之间存在强依赖关系,如果元素类的接口发生改变,那么访问者类也需要相应地进行修改。

2.破坏封装性:访问者模式要求元素类暴露其内部细节,这可能会破坏元素类的封装性。

3.适用性有限:如果对象结构中的元素类型经常变化,那么使用访问者模式会增加系统的维护成本。

不使用访问者模式的实现

如果不使用访问者模式,可以通过在元素类中直接添加操作方法来实现类似的效果。例如,在上面的例子中,可以在Mouse、Keyboard、Monitor和Computer类中分别添加清洁和升级的方法。但是,这种方式会导致每个元素类都包含大量的操作方法,违反了单一职责原则,并且在需要添加新的操作时,需要修改所有元素类的代码,不符合开闭原则。

1.具体元素

// 鼠标
class Mouse {
    public void clean() {
        System.out.println("清洁鼠标");
    }

    public void upgrade() {
        System.out.println("升级鼠标驱动");
    }
}
// 键盘
class Keyboard {
    public void clean() {
        System.out.println("清洁键盘");
    }

    public void upgrade() {
        System.out.println("升级键盘驱动");
    }
}
// 显示器
class Monitor {
    public void clean() {
        System.out.println("清洁显示器");
    }

    public void upgrade() {
        System.out.println("升级显示器驱动");
    }
}
class Computer {
    private List<ComputerPart> parts;

    public Computer() {
        parts = new ArrayList<>();
        parts.add(new Mouse());
        parts.add(new Keyboard());
        parts.add(new Monitor());
    }

    public void clean() {
        System.out.println("清洁电脑");
        for (ComputerPart part : parts) {
            part.clean();
        }
    }

    public void upgrade() {
        System.out.println("升级电脑系统");
        for (ComputerPart part : parts) {
            part.upgrade();
        }
    }
}

2.测试类

// 使用示例
public class NoVisitorPatternDemo {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.check();
        computer.clean();
        computer.upgrade();
    }
}

相关文章:

  • 计算机网络 - OSI 七层模型
  • 笔记:分享如何使用github静态页面搭建个人页面
  • 【2025】基于springboot+uniapp的企业培训打卡小程序设计与实现(源码、万字文档、图文修改、调试答疑)
  • 专访成都昭音科技Jackal:AI内容营销助力中企走向全球
  • 鸿蒙学习笔记(2)-国际化配置、ArkTS简述
  • 【Javaweb】b站黑马视频学习笔记(导览)
  • 多模态大模型Qwen 和 Qwen2 的模型结构、训练方式与数据处理对比分析
  • 安卓应用兼容新方案:Android Translation Layer(ATL)
  • 抽奖的诱惑系统注册与登录功能测试报告
  • 机器学习都有哪些算法?
  • 大模型技术在商品归一和商品预测中的应用
  • 5.5 位运算专题:LeetCode 面试题 17.19. 消失的两个数字
  • 重庆邮电大学笔试F021 考纲解析
  • 批量将PPT转换成多张图片
  • Qt6相对Qt5的主要提升(AI总结)
  • 军事级加密通信系统——基于QML的战术地图加密传输
  • Session模拟登录与退登
  • python安装教程
  • ETL:数据清洗、规范化和聚合的重要性
  • ATT 汇编常用指令
  • 商务部:对原产于美国、欧盟、台湾地区和日本的进口共聚聚甲醛征收反倾销税
  • 天算星座二期首批卫星成功发射,将助力6G空天信息基础设施建设
  • 淮安市车桥中学党总支书记王习元逝世,终年51岁
  • 朱雀二号改进型遥二运载火箭发射成功
  • 泽连斯基抵达安卡拉,称乌将派出最高级别代表团参与谈判
  • 有人倒卖试运营门票?上海乐高乐园:这些票存在无法入园风险