观察者模式(发布订阅模式)

观察者模式 简述

  • 观察者模式又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
  • 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
  • 观察者设计模式三要素:
  1. 事件源:触发事件的对象,需要注册监听器
  2. 监听器:一般设计成接口,由使用者来实现其中的它想要监听的方法
  3. 事件:触发的事件,里面要封装事件源
  4. 最后是用户实现监听

开发步骤

  • 假设现在要监听学生(Student)小明的学习(study)和睡觉(sleep)情况

事件源

package test.publish;

/**
 * Created by Administrator on 2018/7/20 0020.
 * 事件源(观察的目标)----下面监听它的study()、 sleep()方法
 * 需要注册监听器
 */
public class Student {
    /**
     * name:学生的普通属性
     * bookName:学习的书名
     * studentListener:学生监听器
     */
    private String name;
    private String bookName;
    private StudentListener studentListener;

    public void study(String bookName) {
        this.bookName = bookName;
        /** 当注册了监听器时,则实施方法监听
         * 监听器方法中含有事件,事件又封装了事件源,而用户实现了监听器
         * 所以每次此方法一运行,用户会先监听到,而且能从事件中获取事件源(Student)数据*/
        if (studentListener != null) {
            studentListener.studyListener(new StudentEven(this));
        }
        System.out.println("我是 " + name + " ,准备学习 " + bookName);
    }

    public void sleep() {
        /** 当注册了监听器时,则实施方法监听,与上同理*/
        if (studentListener != null) {
            studentListener.sleepListener(new StudentEven(this));
        }
        System.out.println("我是 " + name + " ,准备睡觉!");
    }

    public String getName() {
        return name;
    }

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

    public String getBookName() {
        return bookName;
    }

    /**
     * 注册监听器
     * 只要当注册了监听器,才能监听方法
     *
     * @param studentListener
     */
    public void addStudentListener(StudentListener studentListener) {
        this.studentListener = studentListener;
    }
}

事件

package test.publish;

/**
 * Created by Administrator on 2018/7/20 0020.
 * 事件---封装事件源,便于事件源对象的传入传出
 * 这样的好处是以后用户可以通过触发的事件获取事件源,从而可以获取数据源的数据
 */
public class StudentEven {

    private Object evenSource;

    public StudentEven(Object evenSource) {
        this.evenSource = evenSource;
    }

    public Object getEvenSource() {
        return evenSource;
    }

    public Student getStudent() {
        return (Student) evenSource;
    }
}

监听器

package test.publish;

/**
 * Created by Administrator on 2018/7/20 0020.
 * 监听学生的监听器,通常设计成接口,让用户自己实现
 * 用户可以从 StudentEven 中获取事件源
 */
public interface StudentListener {
    /**
     * 监听器监听的方法
     *
     * @param studentEven 监听器监听的事件
     */
    void studyListener(StudentEven studentEven);

    void sleepListener(StudentEven studentEven);
}

用户监听

package test.publish;

/**
 * Created by Administrator on 2018/7/20 0020.
 * 自己实现监听器,这和使用Java Web的监听器道理是一样的
 * 如果只想监听里面的部分方法,则可以再加适配器
 */
public class MyStudentListener implements StudentListener {
    @Override
    public void studyListener(StudentEven studentEven) {
        Student student = studentEven.getStudent();
        System.out.println("-----------监听到 " + student.getName() + " 开始学习 " + student.getBookName());
    }

    @Override
    public void sleepListener(StudentEven studentEven) {
        Student student = studentEven.getStudent();
        System.out.println("-----------监听到 " + student.getName() + " 开始睡觉");
    }
}

测试结果

/**
 * Created by Administrator on 2018/7/20 0020.
 * 未注册监听器时
 */
public class MyTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("小明同学");
        student.study("论语");
        student.sleep();
    }
}
//输出如下
//我是 小明同学 ,准备学习 论语
//我是 小明同学 ,准备睡觉!
//Process finished with exit code 0
/**
 * Created by Administrator on 2018/7/20 0020.
 * 注册监听后
 */
public class MyTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("小明同学");
        student.addStudentListener(new MyStudentListener());
        student.study("论语");
        student.sleep();
    }
}


/*
-----------监听到 小明同学 开始学习 论语
        我是 小明同学 ,准备学习 论语
        -----------监听到 小明同学 开始睡觉
        我是 小明同学 ,准备睡觉!

        Process finished with exit code 0
*/

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/81125809