设计模式-观察者模式-java

介绍

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种

它定义了一种 一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

理解

主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝(粉丝肯定是多个)

角色

Subject

主题,即:被观察者,Observable,一般是普通类 或 抽象类

  • 把所有 观察者 保存在一个 集合 里,即:可以有任意数量的观察者,可以增加和删除观察者

  • 主题的状态,就是 成员变量,一般是 boolean 类型

  • 通知方法,给所有观察者发送通知

什么是发通知?

答:就是 被观察者 调用 观察者(多个) 的某个方法

如何发通知?

答:状态发生改变后,发送通知给观察者

ConcreteSubject

具体的被观察者类,该类的状态发生改变时,给所有观察者发送通知。

Observer

观察者,一般是接口

至少有一个通知方法

ConcrereObserver

具体观察者,观察者实现类,实现观察者接口

通知方法:被观察者通知观察者时,其实就是调用该方法

java 内置观察者相关类

  • 观察者:实现 java.util.Observer 接口,实现 update() 方法,当 被观察者 通知 观察者时,会调用该方法

  • 被观察者类:需要继承 java.util.Observable

    • addObserver() 方法添加观察者

    • 当被观察者发生了改变,就需要调用 setChanged() 方法,将标志变量 changed 修改为 true

    • 使用notifyObservers() 方法通知所有的观察者,即:调用 观察者的 update() 方法。并将标志变量 changed 置回原值 false
      关键:必须先调用 setChanged() 方法,否则不会通知

例子

主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝

使用 java自带类实现

观察者实现类

粉丝是观察者

package 观察者.java自带类;

import 观察者.Fans;

import java.util.Observable;
import java.util.Observer;

public class FansImpl implements Observer {
    private String name;

    public FansImpl(String name) {
        this.name = name;
    }

    // 被观察者发通知时,调用该方法
    @Override
    public void update(Observable o, Object msg) {
        System.out.println(msg);
        Zhubo zhubo = (Zhubo)o;
        System.out.println(name+"说:不学了,看 "+zhubo.getName() + "直播");

    }
}

被观察者类

主播是被观察者

package 观察者.java自带类;

import java.util.Observable;

/**
 * 主播类,相当于被观察者
 */
public class Zhubo extends Observable {
    private String name;

    public Zhubo(String name) {
        this.name = name;
    }

    /**
     * 开播,也就是修改状态
     */
    public void kaibo(){
        // ※※※※必须先调用该方法,否则通知方法无效※※※
        setChanged();
        // 发通知
        notifyObservers(name+"开播啦,快来呀!");
    }

    public String getName() {
        return name;
    }
}

测试类

package 观察者.java自带类;

import java.util.Observer;

public class Main {
    public static void main(String[] args) {

        Zhubo lilei = new Zhubo("李雷");

        Observer hanmeimei = new FansImpl("韩梅梅");
        Observer lili = new FansImpl("lili");
        Observer lucy = new FansImpl("lucy");

        lilei.addObserver(hanmeimei);
        lilei.addObserver(lili);
        lilei.addObserver(lucy);
        System.out.println("观察者数量:"+lilei.countObservers());

        lilei.kaibo(); // 开播


        System.out.println("------------ 移除 lucy--------");
        lilei.deleteObserver(lucy);
        System.out.println("观察者数量:"+lilei.countObservers());

        lilei.kaibo(); // 必须先开播,否则不会发送通知
        lilei.notifyObservers();
    }
}

执行结果:

观察者数量:3
李雷开播啦,快来呀!
lucy说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
lili说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
韩梅梅说:老娘不学了,看 李雷直播
------------ 移除 lucy--------
观察者数量:2
李雷开播啦,快来呀!
lili说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
韩梅梅说:老娘不学了,看 李雷直播

例子

主播是被观察者,粉丝是观察者,当主播开播时,发通知给所有的粉丝

完全自定义,可更好的理解细节

观察者接口

粉丝是观察者

package 观察者;

/**
 * 粉丝接口(相当于观察者接口)
 */
public interface Fans {

    /**
     * 主播(被观察者)通知粉丝(被观察者),就是调用该方法
     * @param zhubo
     * @param msg
     */
    public void jinZhiBoJian(Zhubo zhubo,String msg);
}

观察者实现类

package 观察者;

public class FansImpl implements Fans{
    private String name;

    public FansImpl(String name) {
        this.name = name;
    }

    @Override
    public void jinZhiBoJian(Zhubo zhubo, String msg) {
        System.out.println(msg);
        System.out.println(name+"说:老娘不学了,看 "+zhubo.getName() + "直播");
    }
}

被观察者类

主播是被观察者

package 观察者;

import java.util.ArrayList;
import java.util.List;

/**
 * 主播类,相当于被观察者
 */
public class Zhubo {
    private String name;
    /**
     * 该集合保存粉丝(粉丝相当于观察者)
     */
    private List<Fans> fansList = new ArrayList();
    /**
     * 是否开播(相当于被观察者中的状态)
     */
    private boolean isKaibo = false;

    public Zhubo(String name) {
        this.name = name;
    }

    /**
     * 添加粉丝(观察者)
     * @param fans
     */
    public void addFans(Fans fans){
        fansList.add(fans);
    }

    /**
     * 删除粉丝(观察者)
     * @param fans
     */
    public void removeFans(Fans fans){
        fansList.remove(fans);
    }

    public void clearFans(){
        fansList.clear();
    }
    /**
     * 开播,也就是修改状态
     */
    public void kaibo(){
        this.isKaibo = true;
    }

    /**
     * 停播,也就是重置状态为初始值
     */
    public void tingbo(){
        this.isKaibo = false;
    }
    public void noticeAll(){
        // 开播(状态为true)时,才会发通知
        if(!isKaibo){
            return;
        }
        for(Fans item:fansList){
            item.jinZhiBoJian(this,name+"开播啦,快来呀!");
        }
        tingbo();
    }


    public String getName() {
        return name;
    }
}

测试类

package 观察者;

public class Main {
    public static void main(String[] args) {

        Zhubo lilei = new Zhubo("李雷");

        Fans hanmeimei = new FansImpl("韩梅梅");
        Fans lili = new FansImpl("lili");
        Fans lucy = new FansImpl("lucy");

        lilei.addFans(hanmeimei);
        lilei.addFans(lili);
        lilei.addFans(lucy);

        lilei.kaibo(); // 必须先开播,否则不会发送通知
        lilei.noticeAll();


        System.out.println("------------ 移除 lucy--------");
        lilei.removeFans(lucy);
        lilei.kaibo(); // 必须先开播,否则不会发送通知
        lilei.noticeAll();
    }
}

执行结果:

李雷开播啦,快来呀!
韩梅梅说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
lili说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
lucy说:老娘不学了,看 李雷直播
------------ 移除 lucy--------
李雷开播啦,快来呀!
韩梅梅说:老娘不学了,看 李雷直播
李雷开播啦,快来呀!
lili说:老娘不学了,看 李雷直播

https://blog.csdn.net/itachi85/article/details/50773358


原文出处:https://malaoshi.top/show_1IX4v6dioI0Y.html