java设计模式(二十)观察者模式

定义

观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

模式结构

在这里插入图片描述

角色职责

1.抽象目标类(Subject):它用一个列表记录当前目标对象有哪些观察者对象,并提供增加、删除观察者对象和通知观察者对象的接口。
2.具体目标类(ConcreteSubject):一个目标对象就是某个具体目标类的对象,一个具体目标类负责定义它自身的事务逻辑,并在状态改变时通知它的所有观察者对象。
3.抽象观察者类(Observer):它为所有的观察者对象都定义了一个名为update的方法(也叫成员函数)。当目标对象的状态改变时,它就是通过调用它的所有观察者对象的update方法来通知它们的。
4.具体观察者类(ConcreteObserver):每个具体观察者类都要重定义Observer类中定义的update方法,在该方法中实现它自己的任务逻辑,当它被通知的时候(目标对象调用它的update方法)就执行自己特有的任务。

代码实现

抽象目标类:

public abstract class Subject {
    private LinkedList<MyObserver> observers = new LinkedList<MyObserver>();

    public void attachObserver(MyObserver obs) {
        observers.add(obs);
    }

    public void detachObserver(MyObserver obs){
        observers.remove(obs);
    }
    //通知所有的观察者对象
    public void notifyObservers() {
        for (MyObserver obs : observers) {
            obs.update((this));
        }
    }
}

具体目标类:

public class Weather extends Subject {
    private float temp;

    public Weather() {
        this.temp = -1000;
    }

    public float getTemperature() {
        return this.temp;
    }

    public void fetchWeatherData() {
        float max = 60;
        float min = -80;
        float newTemp = (float) (Math.random() * (max - min) + min);

        if (newTemp != this.temp) {
            this.temp = newTemp;
            notifyObservers();
        }
    }
}

抽象观察者:

public interface MyObserver {
    public void update(Subject subject);
}

具体观察者:

public class CelsiusView implements MyObserver {
    @Override
    public void update(Subject subject) {
        if (subject instanceof Weather) {
            Weather weather = (Weather) subject;
            float temperature = weather.getTemperature();
            System.out.println("摄氏温度View:" + temperature);
        }
    }
}


public class WearView implements MyObserver {
    @Override
    public void update(Subject subject) {
        if (subject instanceof Weather) {
            Weather weather = (Weather) subject;
            float temperature = weather.getTemperature();
            if (temperature < 10) {
                System.out.println("穿衣服建议View:十分寒冷,请穿羽绒服。");
            }else if(temperature < 20){
                System.out.println("穿衣服建议View:比较凉爽,多穿点。");
            } else if (temperature < 30) {
                System.out.println("穿衣服建议View:比较温暖,可以穿薄点。");
            } else {
                System.out.println("穿衣服建议View:非常炎热,少穿点。");
            }
        }
    }
}

测试结果:

public class App {
    public static void main(String[] args) {
        Weather weather = new Weather();

        //创建两个观察者对象
        CelsiusView celsiusView = new CelsiusView();
        WearView wearView = new WearView();

        weather.attachObserver(celsiusView);
        weather.attachObserver(wearView);

        weather.fetchWeatherData();
        System.out.println("\n");

        weather.fetchWeatherData();
    }
}

摄氏温度View:14.774444
穿衣服建议View:比较凉爽,多穿点。


摄氏温度View:-64.72526
穿衣服建议View:十分寒冷,请穿羽绒服。

适用场景

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

优缺点

优点:
1、易于扩展:一个观察目标可以对应多个观察者,而这些观察者之间没有相互联系,所以能够根据需要增加和删除观察者,使得系统更易于扩展,符合开闭原则;
2、松耦合,虽然彼此不清楚对方的细节,但依然可以交互,目标对象只知道一个具体的观察者列表,但并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。
缺点:
1、耗时:如果存在很多个被观察者的话,那么将需要花费一定时间通知所有的观察者。
2、如果观察者与被观察者之间存在循环依赖的话,那么可能导致系统崩溃,并且观察者模式没有相应的机制让观察者知道被观察对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走进IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值