设计模式-观察者模式

这次主要记录下观察者模式的学习过程


一、什么是观察者模式

  • 观察者模式(Observer Pattern):
    定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,
    该主题对象会在其状态发生改变时,通知所有观察者对象,使它们能够自动更新自己
  • 优点:
    • 通知者类 (主题类) 与观察者类之间抽象耦合,双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响到另一边的变化
    • 支持广播通信,当通知者类 (主题类) 状态发生改变时,会通知所用注册过的观察者
  • 缺点:
    • 如果一个通知者类 (主题类) 有很多的直接或间接的观察者的话,将所有的观察者都通知到会花费很多时间
    • 如果通知者类 (主题类) 与观察者类之间存在循环依赖,通知者类 (主题类) 会触发它们之间的循环调用,从而导致系统崩溃
    • 观察者无法获知通知者类 (主题类) 是如何发生变化的,而仅仅只是知道通知者类 (主题类) 发生了变化
  • 使用场景:
    • 一个抽象模型有两个方面,其中一方面依赖于另一方面,用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用
    • 一个对象的改变将导致其他一个或多个对象也发生改变,而不需要知道具体有多少个对象将发生改变,可以降低对象之间的耦合度

二、观察者模式UML图

设计模式-观察者模式


三、观察者模式示例

老师类 (即抽象通知者类或抽象主题类)
将所有观察者对象的引用保存在一个集合里,每个主题都可以拥有任意数量的观察者

/**
 * @Title: Teacher.java
 * @Description: 老师类(即抽象通知者类或抽象主题类)
 * @Author: xj
 * @Date: 2018/10/13 11:15
 */
public abstract class Teacher {

    private List<Student> students = new ArrayList<>();

    /**
     * 添加学生(即添加观察者)
     *
     * @param student
     */
    public void attach(Student student) {
        students.add(student);
    }

    /**
     * 移除学生(即移除观察者)
     *
     * @param student
     */
    public void detach(Student student) {
        students.remove(student);
    }

    /**
     * 通知学生(即通知观察者)
     */
    public void notifyStudent() {
        students.forEach(Student::update);
    }
}

语文老师类 (即具体通知者类或具体主题类)
具体主题,将有关状态存入具体观察者对象中,在具体主题的内部状态发生改变时,会通知所有注册过的观察者

/**
 * @Title: ChineseTeacher.java
 * @Description: 语文老师类(即具体通知者类或具体主题类)
 * @Author: xj
 * @Date: 2018/10/13 11:32
 */
public class ChineseTeacher extends Teacher {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

学生类 (即抽象观察者类)
为所有的具体观察者定义一个接口,在得到主题的通知时更新自己

/**
 * @Title: Student.java
 * @Description: 学生类(即抽象观察者类)
 * @Author: xj
 * @Date: 2018/10/13 11:17
 */
public abstract class Student {

    /**
     * 更新方法
     */
    public abstract void update();
}

具体学生类 (即具体观察者类)
实现更新接口,使本身的状态与主题的状态保持一致

/**
 * @Title: XiaoMing.java
 * @Description: 具体学生类(即具体观察者类)
 * @Author: xj
 * @Date: 2018/10/13 11:34
 */
public class XiaoMing extends Student {

    private String message;
    private ChineseTeacher chineseTeacher;

    public XiaoMing(ChineseTeacher chineseTeacher) {
        this.chineseTeacher = chineseTeacher;
    }

    @Override
    public void update() {
        this.message = chineseTeacher.getMessage();
        System.out.println("语文老师: 小明," + message);
    }
}

具体学生类 (即具体观察者类)
实现更新接口,使本身的状态与主题的状态保持一致

/**
 * @Title: XiaoHong.java
 * @Description: 学生类(即抽象观察者类)
 * @Author: xj
 * @Date: 2018/10/13 11:36
 */
public class XiaoHong extends Student {

    private String message;
    private ChineseTeacher chineseTeacher;

    public XiaoHong(ChineseTeacher chineseTeacher) {
        this.chineseTeacher = chineseTeacher;
    }

    @Override
    public void update() {
        this.message = chineseTeacher.getMessage();
        System.out.println("语文老师: 小红," + message);
    }
}

测试类

/**
 * @Title: Test.java
 * @Description: 测试类
 * @Author: xj
 * @Date: 2018/10/13 11:54
 */
public class Test {

    public static void main(String[] args) {
        ChineseTeacher chineseTeacher = new ChineseTeacher();
        chineseTeacher.attach(new XiaoMing(chineseTeacher));
        chineseTeacher.attach(new XiaoHong(chineseTeacher));
        chineseTeacher.setMessage("快写作业!!!");
        chineseTeacher.notifyStudent();
    }
}

输出结果
设计模式-观察者模式


以上就是抽象工厂观察者模式的一个小例子