设计模式系统回顾(6)观察者模式(发布订阅模式)

本文详细介绍了Java中的观察者模式,包括push和pull两种模式的实现。通过WeatherData和WeatherDisplay的例子展示了如何创建和管理观察者。同时,也提到了JDK自带观察者模式的局限性,如Observable类的复用性问题和方法保护等。文章还讨论了观察者模式的适用场景、优缺点,并给出了一个关于社交动态发布和接收的示例。最后,指出了Java中观察者模式在数据实时监听和扩展性方面的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其目的是定义对象之间的一对多以来,让多个观察者对象同时监听一个对象

push模式(set)

public interface Observer {
    void update(float temperature);//更新天气信息
}
//管理观察者
public interface Subject {
    void registerObserver(Observer o);//注册观察对象
    void removeObserver(Observer o);//移除观察对象
    void notifyObservers();//通知观察对象
}

//被观察者
public class WeatherData implements Subject {
    private List<Observer> observers;//观察者不止一个,所以用list进行维护

    private float temperature;//温度

    public void setMessurements(float temperature){
        this.temperature = temperature;

        notifyObservers();//气温信息发生变化时,通知所有观察者
    }


    public WeatherData() {//初始化list
        this.observers = new ArrayList<>();
    }

    /**
     * 注册观察者
     * @param o
     */
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    /**
     * 移除观察者
     * @param o
     */
    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if(i >= 0){
            observers.remove(i);
        }

    }

    /**
     * 通知所有观察者
     */
    @Override
    public void notifyObservers() {
        for (Observer observer : observers){//遍历所有观察者
            observer.update(temperature);//通知观察者更新数据信息
        }
    }
}


//观察者
public class WeatherDisplay implements Observer {
    private Subject subject;//维护观察者
    private float temperature;//温度

    public WeatherDisplay(Subject subject) {//注册监听对象
        this.subject = subject;
        subject.registerObserver(this);
    }


    @Override
    public void update(float temperature) {//当被观察者气温发生变化会调用这个方法,也就等于更新了观察者对象的数据
        this.temperature = temperature;
    }

    public void display(){
        System.out.println("当前最新的温度为:" + temperature);
    }
}

pull 模式

//记录动态信息
public class Trends {
    private String nickName;//发表动态的用户昵称

    private String content;//发表的动态内容

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


//(被观察者),继承 JDK 自带的被观察者对象:Observable
public class Zone extends Observable {
    //发表动态
    public void publishTrends(Trends trends){
        System.out.println(trends.getNickName() + "发表了一个动态【" + trends.getContent() + "】" );
        setChanged();//占位,只是设置一个标记说明数据改变了
        notifyObservers(trends);//通知所有观察者
    }
}

//(观察者),实现 JDK 自带的观察者接口:Observer
public class Friends implements Observer {
    private String name;//看动态的人名

    public String getName() {
        return name;
    }

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

    @Override
    public void update(Observable o, Object arg) {//获取(空间)被观察者数据
        Trends trends = new Trends();
        if(null != arg && arg instanceof Trends){
            trends = (Trends)arg;
        }
        System.out.println(this.getName() + ",您好!您收到了来自" + trends.getNickName() +
                "的一条动态【" + trends.getContent() + "】" + "快去点赞吧!");
    }
}

JDK 自带的观察者模式的局限性:

  • JDK 自带的观察者模式虽然可以主动去 pull 自己需要的数据,但也同时存在以下两个问题:
  • Observable 是一个类而不是一个接口,所以复用性就不是很好,如果某类同时想具有 Observable 类和另一个超类的行为,就会有问题,毕竟 Java 不支持多继承。
  • Observable 将关键的方法保护起来了,比如 setChanged 方法,也就是我们只能继承 Observable 类才能实现想要的功能,这个违反了合成复用原则.

适用场景:
需要实时监听数据
优点:
扩展性好,要扩展观察者只需要新建观察者并注册进去就可以
缺点:
被观察者对象过多时,会使得系统复杂难以维护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值