设计模式——观察者模式

观察者模式

百度百科上的定义:
观察者模式(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

应用场景

观察者模式多用于实现订阅功能的场景,例如消息事件的订阅,当我们订阅了某个消息事件时,当这个事件发布了新的消息,就会通知我们。

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  2. 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。
  3. 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,不希望这些对象是紧密耦合的。

实现逻辑

Java已经支持观察者模式

  • java.util.Observable :抽象主题
  • java.util.Observer :抽象观察者

具体代码

  1. 创建一个Java Entity,模拟需要发布/订阅的消息OfficeInfo

import lombok.Data;

import java.util.Objects;

@Data
public class OfficeInfo {
    private int length;
    private int width;
    private int hight;

    public OfficeInfo(int length, int width, int hight) {
        this.length = length;
        this.width = width;
        this.hight = hight;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        OfficeInfo that = (OfficeInfo) o;
        return length == that.length &&
                width == that.width &&
                hight == that.hight;
    }

    @Override
    public int hashCode() {
        return Objects.hash(length, width, hight);
    }
}
  1. 创建消息生产类,也就是被观察类
import java.util.Observable;

public class Watched extends Observable {
    private OfficeInfo officeInfo;

    public OfficeInfo getOfficeInfo() {
        return officeInfo;
    }

    public void setOfficeInfo(OfficeInfo officeInfo) {
        if (this.officeInfo == null || !this.officeInfo.equals(officeInfo)) {
            this.officeInfo = officeInfo;
            setChanged();
        }
        notifyObservers();
    }
}

Notice:
Watched继承Observable类,在其消息发生变化时,调用Observable的setChanged方法,记录消息发生了变化,并使用notifyObservers方法将该变化通知给所有订阅了该事件的观察者们。

  1. 创建两个消息消费类,也是观察者类
import lombok.extern.slf4j.Slf4j;

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

@Slf4j
public class Watcher1 implements Observer {

    public Watcher1(Observable o) {
        o.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        OfficeInfo info = ((Watched) o).getOfficeInfo();
        log.info("Watcher1:状态发生改变:length:{},width:{},hight:{}", info.getLength(), info.getWidth(), info.getHight());
    }
}

Notice:
Watcher1 在构造方法中,将自身this注册进被观察者的订阅名单中,并实现了Observer 的update接口,用于接收被观察者发布的消息。

import lombok.extern.slf4j.Slf4j;

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

@Slf4j
public class Watcher2 implements Observer {

    public Watcher2(Observable o) {
        o.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        OfficeInfo info = ((Watched) o).getOfficeInfo();
        log.info("Watcher2:状态发生改变:length:{},width:{},hight:{}", info.getLength(), info.getWidth(), info.getHight());
    }
}
  1. 测试
public class ObserverDemo {
    public static void main(String[] args) {
        //创建被观察者对象
        Watched watched = new Watched();
        //创建观察者对象,并将被观察者登记注册
        new Watcher1(watched);
        new Watcher2(watched);
        //给观察者赋值
        watched.setOfficeInfo(new OfficeInfo(1,2,3));
        watched.setOfficeInfo(new OfficeInfo(4,5,6));
        watched.setOfficeInfo(new OfficeInfo(7,8,9));
    }
}

Notice:
初始化创建被观察类Watched
并新建两个观察者类Watcher1和Watcher2,将自己注册进Watched的订阅列表中;
在验证的时候,只需要将OfficeInfo初始化赋值后,即可验证两个观察者是否能收到消息

  1. 测试结果
14:46:17.709 [main] INFO observer.Watcher2 - Watcher2:状态发生改变:length:1,width:2,hight:3
14:46:17.722 [main] INFO observer.Watcher1 - Watcher1:状态发生改变:length:1,width:2,hight:3
14:46:17.723 [main] INFO observer.Watcher2 - Watcher2:状态发生改变:length:4,width:5,hight:6
14:46:17.723 [main] INFO observer.Watcher1 - Watcher1:状态发生改变:length:4,width:5,hight:6
14:46:17.723 [main] INFO observer.Watcher2 - Watcher2:状态发生改变:length:7,width:8,hight:9
14:46:17.723 [main] INFO observer.Watcher1 - Watcher1:状态发生改变:length:7,width:8,hight:9

通过测试验证得到的结果,是Watcher1和Watcher2都能同时发生状态变化,都能接收到主题类的消息。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值