【java_设计模式】访问者模式

学习路径: https://coding.imooc.com/class/270.html

  • 前言
    “访问者模式一般开发中比较少用,但是如果需要用到了,该模式将是最佳实现”
  • 应用场景
    网课有免费课程、实战课程(付费)。访问课程的角色有学生、老师。存在以下四种行为:
    老师访问免费课程、老师访问付费课程、学生访问免费课程、学生访问付费课程。
    代码上如果要拓展访问者的行为,可以考虑采用访问者模式
   public static void main(String[] args) {
        // 两类课程
        Course freeCourse = new FreeCourse("MVC的理解");
        Course codingCourse = new CodingCourse("JVM内存分析", 14);
        // 两个访问者
        Visitor studentVisitor = new StudentVisitor();
        Visitor teacherVisitor = new TeacherVisitor();
        
        // 课程容器,抽象容器:Course的子类
        ArrayList<Course> courseArrayList = new ArrayList<>();
        courseArrayList.add(freeCourse);
        courseArrayList.add(codingCourse);
        // 访问者容器,抽象容器:Visitor的实现类
        ArrayList<Visitor> visitorArrayList = new ArrayList<>();
        visitorArrayList.add(studentVisitor);
        visitorArrayList.add(teacherVisitor);
        
        // 两种容器进行循化嵌套
        for (Visitor visitor : visitorArrayList) {
            for (Course course: courseArrayList) {
                // 抽象对象(抽象类的子类)调用方法,方法参数也为抽象对象(接口的实现类)
                course.accept(visitor);
            }
        }
        
    }
  • 实现
/**
 *  课程抽象类
 */
public abstract class Course {
    // 开放权限让子类重写
    protected String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 定义应用层方法,每个子类自己改写,入参是访问者
     * @param visitor
     */
    public abstract void accept(Visitor visitor);
}

/**
 * 抽象课程的子类
 */
public class FreeCourse extends Course{
    public FreeCourse(String name) {
        this.name = name;
    }

    /**
     * 核心方法:
     * 传入Visitor对象,
     * 内部调用Visitor对象的visit方法,参数为调用者(自己)
     * 该方法联系了访问者和课程的两个抽象对象
     * @param visitor 访问者
     */
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
/**
 * 访问者接口,访问不同的课程有不同的行为。
 * 该模式下,尽量确定被访问者的数量,不然拓展接口实现会造成大量代码修改
 */
public interface Visitor {
    void visit(CodingCourse codingCourse);

    void visit(FreeCourse freeCourse);
}
/**
 * 实现访问者接口,自定义访问者访问不同课程的业务逻辑
 * 如果要新增一个访问者,新增一个类即可
 */
public class StudentVisitor implements Visitor {
    @Override
    public void visit(CodingCourse codingCourse) {
        System.out.println("学生角色查看" + "实战课程: "+ codingCourse.getName());
    }

    @Override
    public void visit(FreeCourse freeCourse) {
        System.out.println("学生角色查看" + "实战课程: "+ freeCourse.getName());
    }
}
  • 拓展

应用层的一段代码,可以修改主被动关系

 for (Visitor visitor : visitorArrayList) {
            for (Course course: courseArrayList) {
                // 抽象对象(抽象类的子类)调用方法,方法参数也为抽象对象(接口的实现类)
                course.accept(visitor);
            }
        }

其中course.accept(visitor);可以改为visitor.visit(course);,但是需要修改接口实现

/**
 * 不同的访问者,有不同的行为
 */
public interface Visitor {
    void visit(CodingCourse codingCourse);

    void visit(FreeCourse freeCourse);

    // jdk1.8 可以在接口写实现
    default void visit(Course course){
        if(course instanceof CodingCourse){
            visit((CodingCourse)course);
        } else if(course instanceof FreeCourse){
            visit((FreeCourse)course);
        } else {
            throw new UnsupportedOperationException("访问权限不支持");
        }
    }
}
  • 总结
    访问者模式加强了访问者的可拓展性,核心是把访问者作为被访问者一方法的入参,并回调访问者的具体方法,参数为被访问者。缺点是,被访问者如上文提到的课程类别,如果新增一个课程类别就要修改Visitor接口,造成大量的代码修改。所以使用访问者模式的时候应该尽量确定被访者是不需要拓展的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值