23种设计模式-行为型模式-观察者模式

本文介绍了观察者模式,一种用于实现对象间一对多关系的行为型模式。通过示例,如前端的双向数据绑定和国家气象网更新多个网站天气信息,解释了模式的工作原理。代码示例展示了如何创建一个气象网络作为被观察者,以及新浪、百度、搜狗等网站作为观察者,当气象数据变化时,观察者会被自动通知并更新信息。
摘要由CSDN通过智能技术生成

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

观察者模式:当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
角色:subject(被观察者)、observer(观察者)、concreteObserver(具体观察者)

博文推荐

菜鸟教程
详解Java设计模式之观察者模式(Observer Pattern)

案例描述

1、双向数据绑定

那我们要怎么理解什么是观察者呢?

了解前端的朋友应该很熟悉双向数据绑定机制,这里就很好体现了观察者模式,通过数据的变化驱动视图。再具体一点就是看下图
在这里插入图片描述
数据只有一份,而产生的视图会有两份甚至多份,当数据发生改变时,与之绑定的视图也会随之改变。
这里的数据可以看成subject(被观察者)、视图看作observer(观察者)。

2、国家气象网

要是还不理解的话,再举个栗子,我们都知道像温度降水量湿度这种信息一般以国家天气气象网为主,像百度、新浪、搜狗这种网站它们收集天气这种信息一般采用的都是第三方接口,也就是国家气象网,就相当于他们订阅了天气这种信息。只要国家气象网的温度、降水量、湿度等天气信息发生了改变,那相应的网站平台气象信息也会随之改变,这里的国家气象网可以理解为subject,而订阅了这类消息的百度、新浪、搜狗网站可以看成observer

UML类图关系

在这里插入图片描述

具体代码如下

以下以国家天气网为例

Subject

package com.lcq.pattern.observer;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 被观察者
 */
public interface Subject {
    /**
     * 注册观察者(订阅)
     *
     * @param observer
     */
    void registerObserver(Observer observer);

    /**
     * 移除观察者(解除订阅)
     *
     * @param observer
     */
    void removeObServer(Observer observer);

    /**
     * 通知观察者(发布)
     */
    void notifyObServer();
}

MeteorologicalNetwork(国家气象网)

package com.lcq.pattern.observer;

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

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 气象网
 */
public class MeteorologicalNetwork implements Subject {
    private int temperature;//温度
    private String precipitation;//降水量
    private int humidity;//湿度
    private List<Observer> observerList;

    public MeteorologicalNetwork(int temperature, String precipitation, int humidity) {
        this.precipitation = precipitation;
        this.temperature = temperature;
        this.humidity = humidity;
        observerList = new ArrayList<>();
    }

    public void changeWeather(int temperature, String precipitation, int humidity) {
        this.temperature = temperature;
        this.precipitation = precipitation;
        this.humidity = humidity;
        notifyObServer();
    }

    @Override
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void removeObServer(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObServer() {
        for (Observer observer : observerList) {
            observer.update(temperature, precipitation, humidity);
        }
    }
}

Observer

package com.lcq.pattern.observer;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 观察者
 */
public interface Observer {
    /**
     * 更新天气
     * @param temperature 温度
     * @param precipitation 降水量
     * @param humidity 湿度
     */
    void update(int temperature,String precipitation,int humidity);
}

Sina(新浪)

package com.lcq.pattern.observer;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 新浪
 */
@Slf4j
@Data
public class Sina implements Observer{

    @Override
    public void update(int temperature, String precipitation, int humidity) {
        log.debug("新浪网 ===> 温度 -> {}℃,降水量 -> {}mm,湿度 -> {}%",temperature,precipitation,humidity);
    }
}

BaiDU(百度)

package com.lcq.pattern.observer;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 百度
 */
@Slf4j
@Data
public class BaiDu implements Observer{

    @Override
    public void update(int temperature, String precipitation, int humidity) {
        log.debug("百度网 ===> 温度 -> {}℃,降水量 -> {}mm,湿度 -> {}%",temperature,precipitation,humidity);
    }
}

SouGou(搜狗)

package com.lcq.pattern.observer;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc 搜狗
 */
@Slf4j
@Data
public class SouGou implements Observer {

    @Override
    public void update(int temperature, String precipitation, int humidity) {
        log.debug("搜狗网 ===> 温度 -> {}℃,降水量 -> {}mm,湿度 -> {}%",temperature,precipitation,humidity);
    }
}

测试

package com.lcq.pattern.observer;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author coder
 * @Date 2023-04-02
 * @Desc
 */
@Slf4j
public class Client {
    public static void main(String[] args) {
        Sina sina = new Sina();//新浪网
        BaiDu baiDu = new BaiDu();//百度网
        SouGou souGou = new SouGou();//搜狗网

        MeteorologicalNetwork mn = new MeteorologicalNetwork(27, "56", 87);
        mn.registerObserver(sina);//新浪订阅
        mn.registerObserver(baiDu);//百度订阅
        mn.registerObserver(souGou);//搜狗订阅

        mn.notifyObServer();//发布通知

        log.debug("---------------------------------------update-------------------------------");

        mn.changeWeather(15,"45",23);

        mn.removeObServer(souGou);//搜狗解除订阅
        log.debug("---------------------------------------update-------------------------------");
        mn.changeWeather(23,"32",43);
    }
}

运行结果

23:17:16.434 [main] - 新浪网 ===> 温度 -> 27℃,降水量 -> 56mm,湿度 -> 87%
23:17:16.440 [main] - 百度网 ===> 温度 -> 27℃,降水量 -> 56mm,湿度 -> 87%
23:17:16.440 [main] - 搜狗网 ===> 温度 -> 27℃,降水量 -> 56mm,湿度 -> 87%
23:17:16.440 [main] - ---------------------------------------update-------------------------------
23:17:16.440 [main] - 新浪网 ===> 温度 -> 15℃,降水量 -> 45mm,湿度 -> 23%
23:17:16.440 [main] - 百度网 ===> 温度 -> 15℃,降水量 -> 45mm,湿度 -> 23%
23:17:16.440 [main] - 搜狗网 ===> 温度 -> 15℃,降水量 -> 45mm,湿度 -> 23%
23:17:16.441 [main] - ---------------------------------------update-------------------------------
23:17:16.441 [main] - 新浪网 ===> 温度 -> 23℃,降水量 -> 32mm,湿度 -> 43%
23:17:16.441 [main] - 百度网 ===> 温度 -> 23℃,降水量 -> 32mm,湿度 -> 43%

从运行结果我们可以看到,一旦国家气象网的天气发生改变(发布通知),只要是订阅了该气象信息的网站,他们的天气信息也会一起同步,而只要观察者取消订阅,国家气象网也不会再同步信息给取消订阅者了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值