设计模式:访问者模式

149 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

定义

是一种行为设计模式,它能将算法与其所作用的对象隔离开来,即将数据结构与数据操作分离,将操作解耦。

理解与举例

个人理解就是,想要让不同的实体根据行为模式访问不同的对象,以下举例

  • 比如家长和校长是访问者,而老师和学生是被访问者。
  • 家长关心的是老师的教学质量和学生的成绩(仅是举例
  • 校长关心的是老师的薪资和学生的健康(仅是举例
  • 校长和家长看待多个同样对象,但是所观察的视角是不一样的,可以用访问者模式

核心实现

在被访问的类里面加一个对外提供接待访问者的接口。

优缺点

优点

  • 开闭原则
  • 单一职责原则
  • 灵活性
  • 扩展性

缺点

  • 每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者
  • 在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限。

代码实践

以下代码实现以最开头的举例来做,实现校长和家长访问访问多个同样对象,但是访问方式不一样

被访问对象

/**
 *  被访问者基类
 * @author 勤任风
 * @date 2022-01-24 18:10
 */
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public abstract class Person {
   public String name;
   /**
    * 核心接受访问方法
    * @param visitor
    * @return
    **/
   public abstract void accept(Visitor visitor);
}
/**
 * 教师
 * @author 勤任风
 * @date 2022-01-24 18:10
 */
@Data
public class Teacher extends Person {
    public Teacher(String name) {
        super(name);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
/**
 * 学生
 * @author 勤任风
 * @date 2022-01-24 18:14
 */
@Data
public class Student extends Person {
    public Student(String name) {
        super(name);
    }

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

}

访问者

访问者接口

public interface  Visitor {
    void visit(Student student);
    void visit(Teacher teacher);
}
/**
 * 校长类
 * @author 勤任风
 * @date 2022-01-24 18:16
 */
@Slf4j
public class Principal implements Visitor {
    @Override
    public void visit(Student student) {
        log.info("校长 希望看到学生 {}的健康信息",student.getName());
    }

    @Override
    public void visit(Teacher teacher) {
        log.info("校长 希望看到教师 {}的薪资水平",teacher.getName());
    }
}
/**
 * @author 勤任风
 * @date 2022-01-24 18:16
 * 家长类
 */
@Slf4j
public class Parent implements Visitor {
    @Override
    public void visit(Student student) {
        log.info("家长 希望看到学生 {}的成绩",student.getName());
    }

    @Override
    public void visit(Teacher teacher) {
        log.info("家长 希望看到教师 {}的教学质量",teacher.getName());
    }
}

数据报表展示

public class Report {
    private List<Person> persons = new LinkedList<>();

    public Report(){
        persons.add(new Student("张三"));
        persons.add(new Student("李四"));
        persons.add(new Teacher("王五"));
        persons.add(new Teacher("赵六"));
    }
    //展示
    public void show(Visitor visitor){
        for(Person person:persons){
            person.accept(visitor);
        }
    }
}

测试

public class VisitorTest {
    public static void main(String[] args){
        Report report = new Report();
        log.info("*******家长看*******");
        report.show(new Parent());
        log.info("*******校长看*******");
        report.show(new Principal());
    }
}

image.png

附上代码结构

image.png

参考