访问者模式(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));
    }
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值