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

访问者模式(Visitor Pattern)

访问者模式

说明

访问者模式(Visitor Pattern)属于行为型模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
该模式是将数据结构与数据操作分离的设计模式,是将作用于某种数据结构中的各元素的操作封装起来。该模式的实施前提是数据结构相对稳定,不会频繁变动,但是作用于结构上的操作又经常变动。

结构

访问者模式的主要角色如下:
抽象访问者(Visitor):即作用于元素操作的抽象,定义了访问具体元素的接口;
具体访问者(Concrete Visitor):根据需求实现对具体元素的操作;
抽象元素(Element):被访问的元素抽象,定义了接收访问者的接口;
具体元素(Concrete Element):被访问的具体元素,实现接收方法;
结构对象(Object Struture):维护了具体元素的集合,并提供方法接收访问者对集合中的元素进行访问。
访问者模式-类结构图

代码案例

业务背景是:某个培训机构只有语文、英语、数学老师,每个科目的老师都有对应的行为,并且行为会随着需求而改变。

反例

/**
 * @program: visitor
 * @description: 老师抽象类
 * @author: wxw
 * @create: 2024-03-14 16:12
 **/
public abstract class Teacher {

    // 姓名
    protected String name;

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

    // 备课
    public abstract void prepareLessons();

    // 上课
    public abstract void giveClass();

    // 布置作业
    public abstract void assignHomework();

    // 批改作业
    public abstract void homeworkCorrecting();
}
/**
 * @program: visitor
 * @description: 语文老师
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class ChineseTeacher extends Teacher{

    public ChineseTeacher(String name) {
        super(name);
    }

    @Override
    public void prepareLessons() {
        System.out.println(String.format("语文老师【%s】开始备课.", this.name));
    }

    @Override
    public void giveClass() {
        System.out.println(String.format("语文老师【%s】开始授课.", this.name));
    }

    @Override
    public void assignHomework() {
        System.out.println(String.format("语文老师【%s】开始布置作业.", this.name));
    }

    @Override
    public void homeworkCorrecting() {
        System.out.println(String.format("语文老师【%s】开始批改作业.", this.name));
    }

}
/**
 * @program: visitor
 * @description: 英语老师
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class EnglishTeacher extends Teacher{

    public EnglishTeacher(String name) {
        super(name);
    }

    @Override
    public void prepareLessons() {
        System.out.println(String.format("英语老师【%s】开始备课.", this.name));
    }

    @Override
    public void giveClass() {
        System.out.println(String.format("英语老师【%s】开始授课.", this.name));
    }

    @Override
    public void assignHomework() {
        System.out.println(String.format("英语老师【%s】开始布置作业.", this.name));
    }

    @Override
    public void homeworkCorrecting() {
        System.out.println(String.format("英语老师【%s】开始批改作业.", this.name));
    }

}
/**
 * @program: visitor
 * @description: 数学老师
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class MathTeacher extends Teacher{

    public MathTeacher(String name) {
        super(name);
    }

    @Override
    public void prepareLessons() {
        System.out.println(String.format("数学老师【%s】开始备课.", this.name));
    }

    @Override
    public void giveClass() {
        System.out.println(String.format("数学老师【%s】开始授课.", this.name));
    }

    @Override
    public void assignHomework() {
        System.out.println(String.format("数学老师【%s】开始布置作业.", this.name));
    }

    @Override
    public void homeworkCorrecting() {
        System.out.println(String.format("数学老师【%s】开始批改作业.", this.name));
    }

}
public class Test {
    public static void main(String[] args) {
        List<Teacher> teachers = new ArrayList<>();
        Teacher zhangsan = new ChineseTeacher("张三");
        Teacher lisi = new MathTeacher("李四");
        Teacher wangwu = new EnglishTeacher("王五");
        teachers.add(zhangsan);
        teachers.add(lisi);
        teachers.add(wangwu);

        for (Teacher t: teachers) {
            System.out.println("============================");
            t.prepareLessons();
            t.giveClass();
            t.assignHomework();
            t.homeworkCorrecting();
            System.out.println("============================");
        }
    }
}

假设培训机构为了提高教学质量,要求所有老师都必须跟同学进行单独沟通,了解每个同学的情况。
这时就需要在Teacher抽象类中添加沟通的方法,所有的子类都得实现该方法,违背了开闭原则。

重构后

抽象元素(Element)

/**
 * @program: visitor
 * @description: 老师抽象类
 *              抽象元素(Element)
 * @author: wxw
 * @create: 2024-03-14 16:12
 **/
public abstract class Teacher {

    // 姓名
    protected String name;

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

    // 接收方法
    public abstract void accept(IActionVisitor actionVisitor);
}

抽象访问者(Visitor)

/**
 * @program: visitor
 * @description: 老师行为访问者接口
 *              抽象访问者(Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:33
 **/
public interface IActionVisitor {

    // 访问语文老师
    void visitorChineseTeacher(ChineseTeacher chineseTeacher);
    // 访问英语老师
    void visitorEnglishTeacher(EnglishTeacher englishTeacher);
    // 访问数学老师
    void visitorMathTeacher(MathTeacher mathTeacher);

}

具体元素(Concrete Element)

/**
 * @program: visitor
 * @description: 语文老师
 *              具体元素(Concrete Element)
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class ChineseTeacher extends Teacher {

    public ChineseTeacher(String name) {
        super(name);
    }

    @Override
    public void accept(IActionVisitor actionVisitor) {
        actionVisitor.visitorChineseTeacher(this);
    }

}

/**
 * @program: visitor
 * @description: 英语老师
 *              具体元素(Concrete Element)
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class EnglishTeacher extends Teacher {

    public EnglishTeacher(String name) {
        super(name);
    }

    @Override
    public void accept(IActionVisitor actionVisitor) {
        actionVisitor.visitorEnglishTeacher(this);
    }

}

/**
 * @program: visitor
 * @description: 数学老师
 *              具体元素(Concrete Element)
 * @author: wxw
 * @create: 2024-03-14 16:15
 **/
public class MathTeacher extends Teacher {

    public MathTeacher(String name) {
        super(name);
    }

    @Override
    public void accept(IActionVisitor actionVisitor) {
        actionVisitor.visitorMathTeacher(this);
    }
}

具体访问者(Concrete Visitor)

/**
 * @program: visitor
 * @description: 备课访问者
 *              具体访问者(Concrete Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:37
 **/
public class PrepareLessonsVisitor implements IActionVisitor {
    @Override
    public void visitorChineseTeacher(ChineseTeacher chineseTeacher) {
        System.out.println(String.format("语文老师【%s】开始备课.", chineseTeacher.name));
    }

    @Override
    public void visitorEnglishTeacher(EnglishTeacher englishTeacher) {
        System.out.println(String.format("英语老师【%s】开始备课.", englishTeacher.name));
    }

    @Override
    public void visitorMathTeacher(MathTeacher mathTeacher) {
        System.out.println(String.format("数学老师【%s】开始备课.", mathTeacher.name));
    }
}

/**
 * @program: visitor
 * @description: 上课访问者
 *              具体访问者(Concrete Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:37
 **/
public class GiveClassVisitor implements IActionVisitor {
    @Override
    public void visitorChineseTeacher(ChineseTeacher chineseTeacher) {
        System.out.println(String.format("语文老师【%s】开始上课.", chineseTeacher.name));
    }

    @Override
    public void visitorEnglishTeacher(EnglishTeacher englishTeacher) {
        System.out.println(String.format("英语老师【%s】开始上课.", englishTeacher.name));
    }

    @Override
    public void visitorMathTeacher(MathTeacher mathTeacher) {
        System.out.println(String.format("数学老师【%s】开始上课.", mathTeacher.name));
    }
}

/**
 * @program: visitor
 * @description: 布置作业访问者
 *              具体访问者(Concrete Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:37
 **/
public class AssignHomeworkVisitor implements IActionVisitor {
    @Override
    public void visitorChineseTeacher(ChineseTeacher chineseTeacher) {
        System.out.println(String.format("语文老师【%s】开始布置作业.", chineseTeacher.name));
    }

    @Override
    public void visitorEnglishTeacher(EnglishTeacher englishTeacher) {
        System.out.println(String.format("英语老师【%s】开始布置作业.", englishTeacher.name));
    }

    @Override
    public void visitorMathTeacher(MathTeacher mathTeacher) {
        System.out.println(String.format("数学老师【%s】开始布置作业.", mathTeacher.name));
    }
}

/**
 * @program: visitor
 * @description: 批改作业访问者
 *              具体访问者(Concrete Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:37
 **/
public class HomeworkCorrectingVisitor implements IActionVisitor {
    @Override
    public void visitorChineseTeacher(ChineseTeacher chineseTeacher) {
        System.out.println(String.format("语文老师【%s】开始批改作业.", chineseTeacher.name));
    }

    @Override
    public void visitorEnglishTeacher(EnglishTeacher englishTeacher) {
        System.out.println(String.format("英语老师【%s】开始批改作业.", englishTeacher.name));
    }

    @Override
    public void visitorMathTeacher(MathTeacher mathTeacher) {
        System.out.println(String.format("数学老师【%s】开始批改作业.", mathTeacher.name));
    }
}

结构对象(Object Struture)

/**
 * @program: visitor
 * @description: 培训机构对象结构
 *              结构对象(Object Struture)
 * @author: wxw
 * @create: 2024-03-14 16:43
 **/
public class TrainingAgency {

    private List<Teacher> teacherList = new ArrayList<>();

    public void addTeacher(Teacher teacher){
        teacherList.add(teacher);
    }

    public void removeTeacher(Teacher teacher){
        teacherList.remove(teacher);
    }

    public void startWork(IActionVisitor visitor){
        System.out.println("================================");
        for (Teacher t: teacherList) {
            t.accept(visitor);
        }
        System.out.println("================================");
    }
}

客户端

public class Test {

    public static void main(String[] args) {
        TrainingAgency trainingAgency = new TrainingAgency();
        trainingAgency.addTeacher(new ChineseTeacher("张三"));
        trainingAgency.addTeacher(new EnglishTeacher("李四"));
        trainingAgency.addTeacher(new MathTeacher("王五"));

        // 备课访问者
        IActionVisitor prepareLessonsVisitor = new PrepareLessonsVisitor();
        trainingAgency.startWork(prepareLessonsVisitor);

        // 上课访问者
        IActionVisitor giveClassVisitor = new GiveClassVisitor();
        trainingAgency.startWork(giveClassVisitor);

        // 布置作业访问者
        IActionVisitor assignHomeworkVisitor = new AssignHomeworkVisitor();
        trainingAgency.startWork(assignHomeworkVisitor);

        // 批改作业访问者
        IActionVisitor homeworkCorrectingVisitor = new HomeworkCorrectingVisitor();
        trainingAgency.startWork(homeworkCorrectingVisitor);
    }
}

增加沟通访问者,无需修改Teacher相关的类

/**
 * @program: visitor
 * @description: 与学生沟通访问者
 *              具体访问者(Concrete Visitor)
 * @author: wxw
 * @create: 2024-03-14 16:37
 **/
public class CommunicationVisitor implements IActionVisitor {
    @Override
    public void visitorChineseTeacher(ChineseTeacher chineseTeacher) {
        System.out.println(String.format("语文老师【%s】开始与学生沟通.", chineseTeacher.name));
    }

    @Override
    public void visitorEnglishTeacher(EnglishTeacher englishTeacher) {
        System.out.println(String.format("英语老师【%s】开始与学生沟通.", englishTeacher.name));
    }

    @Override
    public void visitorMathTeacher(MathTeacher mathTeacher) {
        System.out.println(String.format("数学老师【%s】开始与学生沟通.", mathTeacher.name));
    }
}

http://www.kler.cn/a/272198.html

相关文章:

  • AI Agent:AutoGPT的使用方法
  • Jenkins-获取build用户信息
  • ThinkPHP 8的多对多关联
  • 数据结构学习记录-队列
  • [创业之路-255]:《华为数字化转型之道》-1-主要章节、核心内容、核心思想
  • Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )
  • Apache-Doris基础概念
  • 什么数据需要存在Redis里?缓存的缺点?怎样进行数据同步?
  • 基于Python的股票市场分析:趋势预测与策略制定
  • Qt文件以及文件夹相关类(QDir、QFile、QFileInfo)的使用
  • 安卓国产百度网盘与国外云盘软件onedrive对比
  • docker快速安装和详细安装-保姆教程
  • 蓝桥杯day2刷题日记
  • React 的 diff 算法
  • Unity中UGUI中的PSD导入工具的原理和作用
  • 146 Linux 网络编程2 ,Socket编程,如何创建Linux 服务器 和linux 客户端
  • QT UI窗口常见操作
  • 【GPT-SOVITS-04】SOVITS 模块-鉴别模型解析
  • API安全集成最佳实践:有效应对安全挑战
  • 如何用Selenium通过Xpath,精准定位到“多个相同属性值以及多个相同元素”中的目标属性值
  • 27-2 文件上传漏洞 - 前端绕过
  • Spring Data访问Elasticsearch----Elasticsearch对象映射
  • Spring MVC文件上传配置
  • 【PyTorch】基础学习:一文详细介绍 torch.load() 的用法和应用
  • 鸿蒙Next 支持数据双向绑定的组件:Checkbox--Search--TextInput
  • [EFI]Lenovo Ideapad 530S-14IKB电脑 Hackintosh 黑苹果efi引导文件